Я изо всех сил пытаюсь понять, что я здесь делаю не так. Я использовал Automapper + Automapper.Attributes (https://github.com/schneidenbach/AutoMapper.Attributes) в решении, и недавно мне пришлось разделить мой проект API на «базовую» библиотеку и исходный API. Automapper не может создать карту, когда файлы классов перемещаются за пределы проекта API. Я установил демонстрационный проект со следующей структурой, чтобы подтвердить эту проблему: (Доступно здесь: https://github.com/greghesom/AutoMapper_Example)
API.Core - Класс собаки
namespace API.Core
{
public class Dog
{
public string Name { get; set; }
}
}
API.Core - класс домашних животных
namespace API.Core
{
[MapsTo(typeof(Dog))]
public class Pet
{
[MapsToProperty(typeof(Dog), "Name")] //Edit: Fixed this typo
public string PetName { get; set; }
}
}
API - класс человека
namespace API.Models
{
[MapsTo(typeof(Customer))]
public class Person
{
[MapsToProperty(typeof(Customer), "FirstName")]
public string Name { get; set; }
}
}
API - Класс клиента
namespace API.Models
{
public class Customer
{
public string FirstName { get; set; }
}
}
API - Запуск
AutoMapper.Mapper.Initialize(cfg => {
typeof(API.WebApiConfig).Assembly.MapTypes(cfg);
});
API - Контроллер
var person = new Person { Name = "John" };
var customer = AutoMapper.Mapper.Map<Customer>(person);//This Works
var dog = new Dog { Name = "Lucky" };
var pet = AutoMapper.Mapper.Map<Pet>(dog);//This throws exception
ИСКЛЮЧЕНИЕ:
An error has occurred. 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. Dog -> Pet (Destination member list) API.Core.Dog -> API.Core.Pet (Destination member list)
Unmapped properties: PetName AutoMapper.AutoMapperConfigurationException at lambda_method(Closure , Dog , Pet , ResolutionContext ) at lambda_method(Closure , Object , Object , ResolutionContext ) at API.Controllers.ValuesController.Get() in c:\users\greg\Source\Repos\AutoMapperTest\API\Controllers\ValuesController.cs:line 26 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
В проекте GITHub есть тестовые примеры с этим конкретным методом, я предлагаю сравнить и запустить эти тесты и проверить эти образцы и ваш код.
@ user1672994 добавьте его в качестве ответа ;-)
Приносим извинения за опечатку в MapsToProperty. Я обновил пример проекта, но проблема все еще существует
Подходит ли вам отображение var customer = new Customer{ Name = "John" }; var person = AutoMapper.Mapper.Map<Person>(customer);? Поскольку вы определили карту для сопоставления человека и курса, в вашем вопросе это сработало. Но в случае Dog вы определили сопоставление для Pet с Dog, но вы пытаетесь сопоставить объект dog с объектом pet (а сопоставление не существует).
Вы когда-нибудь находили решение этого? Я наткнулся на эта статья и попробовал, и это, похоже, сработало, но простое использование services.AddAutoMapper() не помогло, не уверен, является ли то, что предлагается в статье, правильным подходом или нет.





MapsToProperty в классе PetName класса Pet объявлен неправильно. Это должно быть typeof (Собака) вместо typeof (Pet).
[MapsTo(typeof(Dog))]
public class Pet
{
[MapsToProperty(typeof(Dog), "Name")]
public string PetName { get; set; }
}
Редактировать
Поскольку вы определили сопоставление для сопоставления Person с Customer, в вашем вопросе это сработало. Но в случае Dog вы определили сопоставление для Pet с Dog, но вы пытаетесь сопоставить объект dog с объектом pet (но сопоставление не существует).
Если вам требуется двухстороннее сопоставление, вам будет предложено определить сопоставление с помощью MapsToAndFromProperty.
Проверьте ссылку это для получения дополнительной информации.
Это была опечатка, я исправил ее, но проблема все еще существует.
Я столкнулся с той же проблемой (AutoMapper 7.0.0). Ключ к проблеме находится в сообщении об ошибке: «AutoMapper создал эту карту типов для вас, но ваши типы не могут быть сопоставлены с использованием текущей конфигурации». Начиная с версии 6.2.0, AutoMapper пытается сам создавать сопоставления для типов, которые не отображаются явно, то есть: во многих случаях создание сопоставления больше не требуется.
Однако кажется, что он использует сопоставления, которые он создает сам, вместо ваших определенных сопоставлений, даже для типов, для которых вы их явно определили. По крайней мере, с этим я столкнулся.
Быстрый способ проверить это: перейти на версию 6.1.1 и посмотреть, сохраняется ли проблема. В моем случае переход на более раннюю версию решил проблему.
У меня есть чувство, что должен быть лучший способ исправить это (или, может быть, это даже ошибка ...), но я пока не знаю, как это сделать. Если найду, отправлю сюда. Просто подумал, что я уже выбросил это здесь, если вам нужно быстрое исправление :)
AM создает карту для вас только тогда, когда не применяется существующая карта.
@LucianBargaoanu Мой конструктор в моем профиле даже не вызывается в любое время от инициализации до момента, когда я вызываю Map для своих объектов. Кажется, что AutoMapper полностью игнорирует мой профиль, но когда я проверяю объект конфигурации, я вижу, что мой профиль зарегистрирован. Я собираюсь выбросить AutoMapper в окно. Что-то действительно напортачило в 7.x
Вы просто упускаете что-л. В противном случае вы могли бы создать суть, который мы можем выполнить и увидеть сбой.
Одна вещь, которую нужно попробовать, - установить CreateMissingTypeMaps в false. Это упрощает понимание.
MapsToProperty в классе PetName класса Pet объявлен неправильно. Это должно быть typeof (Собака) вместо typeof (Pet).