Automapper автоматически разрешает правильный подкласс для сопоставления с? - PullRequest
9 голосов
/ 28 апреля 2011

Имеются следующие типы источников:

public class BaseViewModel
{
   public string Prop1 { get; set; }
}

public class FirstViewModelImpl : BaseViewModel
{
   public string Prop2 { get; set; } 
}

public class SecondViewModelImpl : BaseViewModel
{
   public string AnotherProp { get; set; }
}

И следующие типы назначения

public class BaseDto
{
   public string Prop1 { get; set; }
}

public class FirstDtoImpl : BaseDto
{
   public string Prop2 { get; set; } 
}

public class SecondDtoImpl : BaseViewModel
{
   public string AnotherProp { get; set; }
}

Со следующими отображениями:

Mapper.CreateMap<FirstViewModelImpl,FirstDtoImpl>();
Mapper.CreateMap<SecondViewModelImpl,SecondDtoImpl>();

Могу ли я сделать следующее (тривиальный пример) - учитывая, что я на самом деле не знаю тип модели представления до времени выполнения?

BaseViewModel myViewModel = GetAViewModelFromSomewhere();
FirstDtoImpl dto = (FirstDtoImpl)Mapper.Map<BaseViewModel,BaseDto>(myViewModel);

Я все равно сейчас пробую!

Ответы [ 4 ]

18 голосов
/ 28 апреля 2011

Я обнаружил, что если я изменю сопоставления на

Mapper.CreateMap<BaseViewModel,BaseDto>()
        .Include<FirstViewModelImpl,FirstDtoImpl>()
        .Include<SecondViewModelImpl,SecondDtoImpl>();

Mapper.CreateMap<FirstViewModelImpl,FirstDtoImpl>();
Mapper.CreateMap<SecondViewModelImpl,SecondDtoImpl>();

Тогда все работает как положено, без использования конвертера типов.

3 голосов
/ 28 апреля 2011

Вы не можете сделать это напрямую, однако можете обойти это с помощью TypeConverter.

В Mappings вы добавите:

Mapper.CreateMap<BaseViewModel, BaseDto>()
    .ConvertUsing<MyTypeConverter>();

Затем вы можете создать конвертер кактак:

public class MyTypeConverter : TypeConverter<BaseViewModel, BaseDto>
{
    protected override BaseDto ConvertCore(BaseViewModel tViewModel)
    {
        BaseDto vResult = null;
        if(tViewModel is FirstViewModelImpl)
        {
            var vSource = tViewModel as FirstViewModelImpl;
            vResult = Mapper.Map<FirstViewModelImpl,FirstDtoImpl>(vSource);
        }
        else if(tViewModel is SecondViewModelImpl )
        {
            var vSource = tViewModel as SecondViewModelImpl ;
            vResult = Mapper.Map<SecondViewModelImpl ,SecondDtoImpl>(vSource);
        }
        return vResult;
    }
}

Тогда вы можете использовать его следующим образом:

BaseDto dto= Mapper.Map<BaseViewModel,BaseDto>(myViewModel);

и иметь dto на самом деле того типа, который вы хотели.Базовые типы друг к другу, хотя.Если это имеет значение, я могу повернуть это немного больше.

1 голос
/ 28 апреля 2011

Можете ли вы использовать вместо этого интерфейс? Кроме того, существует неуниверсальная реализация Mapper.Map, которая может работать лучше в этом случае. Если у вас настроено отображение, вы можете просто передать тип.

0 голосов
/ 28 апреля 2011

Нет, это неправильно, если вы создаете Mapping для производных типов, что следует делать, когда объекты карты также указывают производный класс

...