Отображение из динамического в тип со свойством, определенным с типом интерфейса - PullRequest
0 голосов
/ 10 января 2019

В связи с этим я хотел бы отобразить dynamic более резкий результат на объект, и у этого объекта есть свойство с типом интерфейса:

public class TargetModel
{
    public int Id { get; set; }
    public IAddress AbstractAddress { get; set; }
}

Бит динамического объекта является прямым, но я не могу настроить AutoMapper, чтобы сообщить ему, как обрабатывать интерфейс.

dynamic sourceModel = new ExpandoObject();

// flat model - id should map to TargetModel, Address01 will map to a nested type Address on TargetModel
sourceModel.Id = 1;
sourceModel.Address01 = "address01";

// for debugging purposes address maps ok from dynamic
Address address = Mapper.Map<Address>(sourceModel);

// this maps, but AbstractAddress is null - I need to config AutoMapper to understand how to map IAddress to Address
TargetModel target = Mapper.Map<TargetModel>(sourceModel);

Я пытался рассказать, как обращаться со свойством:

CreateMap<ExpandoObject, TargetModel>()
    .ForMember(y => y.AbstractAddress, opts => opts.MapFrom(f => f));

Что не получается с:

System.ArgumentException: не удается создать экземпляр типа интерфейса

Поэтому я попытаюсь намекнуть на бетон:

CreateMap<IAddress, Address>().As<Address>();

Что не решает проблему, и остается исключение.

Я рассмотрел следующие вопросы / концепции и попробовал различные варианты конфигурации, но не смог заставить карту работать:

1 Ответ

0 голосов
/ 10 января 2019

Это попытка сопоставить string в ExpandoObject с IAddress в вашем типе цели. Очевидно, что он не может создать экземпляр IAddress для заполнения, поэтому вы должны выполнить это самостоятельно в отображении.

Если ваши модели выглядят так:

public class TargetModel
{
    public int Id { get; set; }
    public IAddress AbstractAddress { get; set; }
}

public interface IAddress
{
    string Address01 { get; set; }
}

public class Address : IAddress
{
    public string Address01 { get; set; }
}

Тогда ваши настройки и настройки могут выглядеть следующим образом:

public void MappingTests()
{
    dynamic sourceModel = new ExpandoObject();

    // flat model - id should map to TargetModel, Address01 will map to a nested type Address on TargetModel
    sourceModel.Id = 1;
    sourceModel.Address01 = "address01";

    Mapper.Initialize(cfg =>
    {
        cfg.CreateMap<ExpandoObject, TargetModel>()
        .ForMember(dest => dest.AbstractAddress, opt => opt.MapFrom(src => new Address() { Address01 = src.First(kvp => kvp.Key == "Address01").Value.ToString() }))
        .ForMember(destinationMember => destinationMember.Id, opt => opt.MapFrom(src => src.First(kvp => kvp.Key == "Id").Value));
    });

    TargetModel target = Mapper.Map<TargetModel>(sourceModel);
}

Я просто использовал его как IEnumerable<KeyValuePair<string, object>>, но вы также можете трактовать объект растяжения как словарь путем приведения.

cfg.CreateMap<ExpandoObject, TargetModel>()
    .ForMember(dest => dest.AbstractAddress, opt => opt.MapFrom(src => new Address() { Address01 = ((IDictionary<string, object>)src)["Address01"].ToString() }))
    .ForMember(destinationMember => destinationMember.Id, opt => opt.MapFrom(src => ((IDictionary<string, object>)src)["Id"]));
...