Ошибка несопоставленных свойств Automapper с отображением простых объектов - PullRequest
0 голосов
/ 30 января 2019

Мне нужно отобразить объект модели, поступающий из API, на мой фактический объект сущности на DbContext.Он используется при создании нового машинного объекта с помощью действия POST.

Как всегда, я создал простую карту для исходных / целевых объектов.В этом случае мы рассматриваем исходный объект как модель API, а целевой объект как сущность.Также модель имеет только подмножество свойств сущности.

Типы источника / назначения

// Destination (entity on DbContext)
public class Machine
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string MnmConfiguration { get; set; }
    public MachineBootStatus Status { get; set; }
    public long MachineDriverId { get; set; }
    public MachineDriver MachineDriver { get; set; }
    public string DriverConfiguration { get; set; }
    public string DriverStatus { get; set; }
}

// Source (from API controller)
public class MachineCreateModel
{
    public string Name { get; set; }
    public string Description { get; set; }
    public string MnmConfiguration { get; set; }
    public long MachineDriverId { get; set; }
}

Конфигурация отображения

public class DomainProfile : Profile
{
    public DomainProfile()
    {
        //CreateMap<MachineCreateModel, Machine>();
        // Update 2019/01/30 with proposed solution
        CreateMap<MachineCreateModel, Machine>(MemberList.Source);
    }
}

Я использую контейнер Unity DIи конфигурация AutoMapper такова:

container = new UnityContainer();
// ... some other configurations...
container.RegisterType<IMapper, Mapper>(new InjectionConstructor(new MapperConfiguration(cfg => cfg.AddProfile<DomainProfile>())));

Версия

Использование AutoMapper v8.0.0.

Ожидаемое поведение

Я ожидаю получить простоеавтоматическое сопоставление без ошибок, поскольку моя исходная модель - это только подмножество свойств целевой модели с такими же именами.

Фактическое поведение

Я получаю эту ошибку о несопоставленных свойствах, когда попадаю в эту строкус кодом:

Machine entity = Mapper.Map<Machine>(request.Machine);
[14:08:34.363 8 2e62361a INF] Creating new machine: TEST M1
[14:08:36.205 8 bd577466 ERR] An unhandled exception has occurred while executing the request.
AutoMapper.AutoMapperConfigurationException:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
=================================================================================================
AutoMapper created this type map for you, but your types cannot be mapped using the current configuration.
MachineCreateModel -> Machine (Destination member list)
MyApplication.Dcs.Application.Models.MachineCreateModel -> MyApplication.Dcs.Domain.Entities.Machine (Destination member list)

Unmapped properties:
Id
Status
MachineDriver
DriverConfiguration
DriverStatus

   at AutoMapper.ConfigurationValidator.AssertConfigurationIsValid(IEnumerable`1 typeMaps)
   at lambda_method(Closure , MachineCreateModel , Machine , ResolutionContext )
   at lambda_method(Closure , Object , Object , ResolutionContext )
   at AutoMapper.Mapper.AutoMapper.IMapper.Map[TDestination](Object source)
   at MyApplication.Dcs.Application.Commands.MachineCreateCommandHandler.Handle(MachineCreateCommand request, CancellationToken cancellationToken) ..Commands\MachineCreateCommand.cs:line 28

Примечание

В моем решении у меня много проектов, и 3 из них используют AutoMapper (одна и та же версия для всех).Есть 3 различных файла DomainProfile.cs (по 1 для каждого проекта) с необходимыми сопоставлениями.В других классах 2 DomainProfile у меня есть некоторые ручные отображения (см. Пример ниже), потому что мне нужно «перевести» объект с итальянскими именами свойств в другой с английскими именами свойств.Таким образом, для каждого сопоставления объектов есть много строк, таких как:

CreateMap<ArticleCreateUpdateModel, Articoli>()
    .ForMember(d => d.Categoria, opt => opt.MapFrom(src => src.Category))
    .ForMember(d => d.CodiceArticolo, opt => opt.MapFrom(src => src.Code))
    .ForMember(d => d.Descrizione, opt => opt.MapFrom(src => src.Description))
    .ForMember(d => d.Famiglia, opt => opt.MapFrom(src => src.Family))
    .ForMember(d => d.Note, opt => opt.MapFrom(src => src.Note))
    ...

Я не знаю, обязывает ли меня использование этих ручных элементов сопоставления для одного или нескольких классов DomainProfileвсегда объяснять все последующие отображения, даже если они должны быть простыми, как в этом примере.

1 Ответ

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

По умолчанию AutoMapper проверяет свойства назначения.Поскольку не существует ни совпадающих свойств, ни конструкций ForMember для набора свойств в вашем типе назначения, вы получаете исключение выше.

Попробуйте вместо этого проверить свойства источника:

CreateMap<ArticleCreateUpdateModel, Articoli>(MemberList.Source)
    .ForMember(d => d.Categoria, opt => opt.MapFrom(src => src.Category))
    // ...

Примечание: С другой стороны, я должен упомянуть, что это типичный случай, когда AutoMapper является избыточным.За исключением тривиальных случаев, я бы никогда больше этим не воспользовался.

Мне приходилось использовать его в проекте более года, но на самом деле он хорош только для того, чтобы делать простые вещи сложнее, чем нужно.Некоторые методы FromDto и ToDto [extension] просто проще, быстрее, проще в отладке и более реагируют на изменения кода.Сопоставление между различными макетами классов или именами свойств часто приводит к тому, что практически столько же кода (или даже больше с тоннами лямбда-выражений), чем простое написание сопоставления вручную.Смотрите также эту ссылку .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...