AutoMapper избегать вложенных циклов - PullRequest
4 голосов
/ 02 июля 2019

В настоящее время я использую Automapper для сопоставления моей модели домена с DTO.Внутри моей модели Домена у меня есть 3 свойства bool (IsHomeowner, IsTenant, IsLivingWithParents), которые используются для установки значения свойства внутри ViewModel, т.е. PersonDTO, называемого LivingStatus

ОднакоЧтобы получить конечный результат, мне нужно пройтись по модели Person, создать словарь для хранения моих значений, а затем с помощью 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;
   }
   }));
}

Ответы [ 2 ]

1 голос
/ 02 июля 2019

Наконец-то нашли лучшее решение, создав 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)));
0 голосов
/ 02 июля 2019

Вы можете избежать всего этого и расширить свой PersonDto таким образом, чтобы затем значения отображались так, как они должны быть, или вы можете написать собственный Resolver для этой цели. Возможно, это не лучший способ поместить логику в сеттер.

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; }
  }

Дайте мне знать, если вы предпочитаете решение с Resolver. Я постараюсь вам помочь.

...