【问题标题】:AutoMapper avoid nested loopsAutoMapper 避免嵌套循环
【发布时间】:2019-07-02 14:13:02
【问题描述】:

我目前正在使用 Automapper 从我的域模型映射到 DTO。在我的里面 域模型我有 3 个布尔属性(IsHomeownerIsTenantIsLivingWithParents)用于设置属性的值 在 ViewModel 内部,即 PersonDTO 称为 LivingStatus

但是,为了获得最终结果,我必须遍历 Person 模型,创建 Dictionary 存储我的值,然后使用AfterMap 创建一个嵌套循环并在其中设置值。

虽然它有效,但不是一个理想的解决方案,因为随着数据的增加,它更有可能造成内存泄漏 大小。

所以想知道 AutoMapper 中是否有任何东西可以避免这种情况?

这是我的代码

查看模型

public class PersonDTO{
  public int Id { get; set; }
  public string FirstName { get; set; }
  public string Surname { get; set; }
  public Status LivingStatus { get; set; }
}

领域模型

public class Person{
   public int Id { get; set; }
   public string FirstName { get; set; }
   public string Surname { get; set; }
   public bool IsHomeOwner { get; set; }
   public bool IsTenant { get; set; }
   public bool IsLivingWithParents { get; set; }
}

public enum Status{
   Homeowner=1,
   Tenant=2,
   LivingWithParents=3
}
public List<PersonDTO> GetEmployee(List<Person> persons)
{
   var livingStatus = new Dictionary<int, Status>();
   foreach (var person in persons)
   {
       if (person.IsHomeOwner)
       {
          livingStatus.Add(person.Id, Status.Homeowner);
       }
       else if (person.IsTenant)
       {
          livingStatus.Add(person.Id, Status.Tenant);
       }
       else
       {
          livingStatus.Add(person.Id, Status.LivingWithParents);
       }
   }

   return _mapper.Map<List<Person>, List<PersonDTO>>(persons, opts => opts.AfterMap((src, dest) { 
   foreach(var person in dest)
   {
     person.LivingStatus = livingStatus.Single(x => x.Key == person.Id).Value;
   }
   }));
}

【问题讨论】:

  • 您说“它有效”,但这甚至无法编译。 personsList&lt;Person&gt; 但您正在访问像 IsHomeOwner 这样存在于单个 Person 上的属性?
  • 好点 @stuartd 我在输入示例时错过了它:) 现在排序
  • 为什么不在映射过程中为该特定属性使用自定义值解析器?

标签: c# automapper dto


【解决方案1】:

通过创建一个处理转换然后在映射配置中使用它的Method 终于找到了一个更好的解决方案:)

private Status TypeConverter(Person person)
{
    if (person.IsHomeOwner)
    {
      return Status.Homeowner;
    }
    else if (person.IsTenant)
    {
      return Status.Tenant;
    }
    else
    {
      return Status.LivingWithParents;
    }

    return person.Status;
}

映射配置

CreateMap<Person, PersonDTO>()
                .ForMember(dest => dest.LivingStatus, opt => opt.MapFrom(src => TypeConverter(src)));

【讨论】:

    【解决方案2】:

    您可以避免所有这些并扩展您的 PersonDto 以使值按应有的方式映射,或者您可以为此目的编写自己的解析器 也许这不是将逻辑放入 setter 的最佳方式。

    public class PersonDto
      {
        private Status status;
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string Surname { get; set; }
    
        public Status LivingStatus
        {
          get => status;
    
          set
          {
            status = value;
    
            switch (status)
            {
              case Status.Homeowner:
                IsHomeOwner = true;
                IsTenant = false;
                IsLivingWithParents = false;
                break;
    
              case Status.LivingWithParents:
                IsHomeOwner = false;
                IsTenant = false;
                IsLivingWithParents = true;
                break;
    
              case Status.Tenant:
                IsHomeOwner = false;
                IsTenant = true;
                IsLivingWithParents = false;
                break;
    
              default:
                throw new ArgumentOutOfRangeException();
            }
          }
        }
    
    
        public bool IsHomeOwner { get; set; }
        public bool IsTenant { get; set; }
        public bool IsLivingWithParents { get; set; }
      }
    

    如果您更喜欢使用解析器的解决方案,请告诉我。我会尽力帮助你的。

    【讨论】:

    • 感谢您的建议。但是我不确定将逻辑放在 setter 中会是一个更好的解决方案。它不会为UnitTesting提供更好的理由
    猜你喜欢
    • 2012-06-25
    • 2017-08-27
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2019-12-26
    相关资源
    最近更新 更多