Я порівняно новий в .NET, і вирішив братися за .NET Core, а не вивчати "старі способи". Тут я знайшов детальну статтю про налаштування AutoMapper для .NET Core , але чи є більш простий посібник для новачка?
Я порівняно новий в .NET, і вирішив братися за .NET Core, а не вивчати "старі способи". Тут я знайшов детальну статтю про налаштування AutoMapper для .NET Core , але чи є більш простий посібник для новачка?
Відповіді:
Я зрозумів це! Ось деталі:
Додайте пакет для введення залежності залежно від функції AutoMapper до свого рішення через NuGet .
Створіть новий клас для картографічного профілю. (Я створив клас в основному каталозі рішення, який називається, MappingProfile.cs
і додаю наступний код.) Я буду використовувати приклад User
і UserDto
об’єкт.
public class MappingProfile : Profile {
public MappingProfile() {
// Add as many of these lines as you need to map your objects
CreateMap<User, UserDto>();
CreateMap<UserDto, User>();
}
}
Потім додайте AutoMapperConfiguration у відповідність, Startup.cs
як показано нижче:
public void ConfigureServices(IServiceCollection services) {
// .... Ignore code before this
// Auto Mapper Configurations
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services.AddMvc();
}
Щоб викликати відображений у коді об'єкт, зробіть щось на зразок наступного:
public class UserController : Controller {
// Create a field to store the mapper object
private readonly IMapper _mapper;
// Assign the object in the constructor for dependency injection
public UserController(IMapper mapper) {
_mapper = mapper;
}
public async Task<IActionResult> Edit(string id) {
// Instantiate source object
// (Get it from the database or whatever your code calls for)
var user = await _context.Users
.SingleOrDefaultAsync(u => u.Id == id);
// Instantiate the mapped data transfer object
// using the mapper you stored in the private field.
// The type of the source object is the first type argument
// and the type of the destination is the second.
// Pass the source object you just instantiated above
// as the argument to the _mapper.Map<>() method.
var model = _mapper.Map<UserDto>(user);
// .... Do whatever you want after that!
}
}
Я сподіваюся, що це допоможе комусь починати свіжіше з ASP.NET Core! Я вітаю будь-які відгуки чи зауваження, оскільки я все ще новачок у світі .NET!
Profile
розташовані заняття
Крок, щоб використовувати AutoMapper з ASP.NET Core.
Крок 1. Встановлення AutoMapper.Extensions.Microsoft.DependencyInjection з NuGet Package.
Крок 2. Створіть папку в розчині, щоб зберегти відображення з назвою "Відображення".
Крок 3. Після додавання папки Mapping ми додали клас з ім'ям " MappingProfile ", це ім'я може зробити що-небудь унікальне і добре зрозуміти.
У цьому класі ми збираємося підтримувати всі відображення.
Крок 4. Ініціалізація Mapper у запуску "ConfigureServices"
У класі запуску нам потрібно ініціалізувати створений нами профіль, а також зареєструвати сервіс автозапчастини.
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
Фрагмент коду, щоб показати метод ConfigureServices, де нам потрібно ініціалізувати та зареєструвати автомат.
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// Start Registering and Initializing AutoMapper
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
// End Registering and Initializing AutoMapper
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}}
Крок 5. Отримайте вихід.
Щоб отримати відображений результат, нам потрібно зателефонувати в AutoMapper.Mapper.Map та передати належне призначення та джерело.
AutoMapper.Mapper.Map<Destination>(source);
CodeSnippet
[HttpPost]
public void Post([FromBody] SchemeMasterViewModel schemeMaster)
{
if (ModelState.IsValid)
{
var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster);
}
}
'Mapper' does not contain a definition for 'initialize'
. Я використовую AutoMapper.Extensions.Microsoft.DependencyInjection
версію 7.0.0
Я хочу поширити відповіді @ theutz - а саме цей рядок:
// services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature.
У AutoMapper.Extensions.Microsoft.DependencyInjection версії 3.2.0 є помилка ( ймовірно ). (Я використовую .NET Core 2.0)
Про це йдеться у цьому випуску GitHub. Якщо ваші класи, що успадковують профіль профілю AutoMapper, існують поза збіркою, де ви запускаєте клас, вони, ймовірно, не будуть зареєстровані, якщо ваша інжекція AutoMapper виглядає так:
services.AddAutoMapper();
якщо ви чітко не вкажете, за якими збірками шукати профілі AutoMapper.
Це можна зробити так у ваших Startup.ConfigureServices:
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
де "асамблеї" та "type_in_assemblies" вказують на збірку, де вказані класи профілю у вашій програмі. Наприклад:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
Я гадаю, (і я наголошую на цьому слові), що через наступну реалізацію безпараметричного перевантаження (вихідний код від GitHub ):
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
ми розраховуємо на CLR, що вже має збірку JITed, що містить профілі AutoMapper, які можуть бути або можуть бути неправдивими, оскільки вони можуть бути зіткнутими лише у разі потреби (детальніше у цьому питанні StackOverflow).
Відповідь theutz тут дуже хороша, я просто хочу додати це:
Якщо ви дозволяєте своєму картографічному профілю успадковуватись MapperConfigurationExpression
замість Profile
, ви можете просто додати тест, щоб перевірити налаштування вашої карти, що завжди зручно:
[Fact]
public void MappingProfile_VerifyMappings()
{
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(mappingProfile);
var mapper = new Mapper(config);
(mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
Я вирішив це таким чином (подібно до вище, але я відчуваю, що це чистіше рішення) для .NET Core 2.2 / Automapper 8.1.1 w / Extensions.DI 6.1.1.
Створіть клас MappingProfile.cs та заповніть конструктор за допомогою Maps (я планую використовувати один клас для зберігання всіх моїх відображень)
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Dest>().ReverseMap();
}
}
У Startup.cs додайте нижче, щоб додати до DI (аргумент збірки призначений для класу, який містить ваші конфігураційні карти, в моєму випадку це клас MappingProfile).
//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));
У Controller використовуйте його так, як і будь-який інший об'єкт DI
[Route("api/[controller]")]
[ApiController]
public class AnyController : ControllerBase
{
private readonly IMapper _mapper;
public AnyController(IMapper mapper)
{
_mapper = mapper;
}
public IActionResult Get(int id)
{
var entity = repository.Get(id);
var dto = _mapper.Map<Dest>(entity);
return Ok(dto);
}
}
MappingProfiles
з , new Type[]{}
як показано в цій відповіді не потрібно.
У моєму Startup.cs (Core 2.2, Automapper 8.1.1)
services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
У моєму проекті доступу до даних
namespace DAL
{
public class MapperProfile : Profile
{
// place holder for AddAutoMapper (to bring in the DAL assembly)
}
}
У моєму визначенні моделі
namespace DAL.Models
{
public class PositionProfile : Profile
{
public PositionProfile()
{
CreateMap<Position, PositionDto_v1>();
}
}
public class Position
{
...
}
services.AddAutoMapper( typeof(DAL.MapperProfile) );
замість цього services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
?
Мені подобається багато відповідей, зокрема, @saineshwar. Я використовую .net Core 3.0 з AutoMapper 9.0, тому відчуваю, що прийшов час оновити його відповідь.
Що працювало для мене, було в Startup.ConfigureServices (...) зареєструвати послугу таким чином:
services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(),
AppDomain.CurrentDomain.GetAssemblies());
Я думаю, що решта відповідей @saineshwar зберігає ідеал. Але якщо когось цікавить мій код контролера:
[HttpGet("{id}")]
public async Task<ActionResult> GetIic(int id)
{
// _context is a DB provider
var Iic = await _context.Find(id).ConfigureAwait(false);
if (Iic == null)
{
return NotFound();
}
var map = _mapper.Map<IicVM>(Iic);
return Ok(map);
}
І мій клас картографування:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Iic, IicVM>()
.ForMember(dest => dest.DepartmentName, o => o.MapFrom(src => src.Department.Name))
.ForMember(dest => dest.PortfolioTypeName, o => o.MapFrom(src => src.PortfolioType.Name));
//.ReverseMap();
}
}
----- EDIT -----
Прочитавши документи, зв'язані в коментарях Лучана Баргаоану, я думаю, що краще трохи змінити цю відповідь.
Параметр services.AddAutoMapper()
(на який був відповідь @saineshwar) більше не працює (принаймні для мене). Але якщо ви використовуєте збірку NuGet AutoMapper.Extensions.Microsoft.DependencyInjection, фреймворк може перевірити всі класи, що розширюють AutoMapper.Profile (як, наприклад, моя, MappingProfile).
Отже, у моєму випадку, коли клас належить до тієї ж виконувальної збірки, реєстрацію послуги можна скоротити до services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(Більш елегантним підходом може бути розширення без параметрів за допомогою цього кодування).
Спасибі, Лучане!
Я використовую AutoMapper 6.1.1 та asp.net Core 1.1.2.
Перш за все, визначте класи профілю, успадковані профілю Class Class Automapper. Я створив інтерфейс IProfile, який порожній, мета лише знайти класи цього типу.
public class UserProfile : Profile, IProfile
{
public UserProfile()
{
CreateMap<User, UserModel>();
CreateMap<UserModel, User>();
}
}
Тепер створіть окремий клас, наприклад, Mappings
public class Mappings
{
public static void RegisterMappings()
{
var all =
Assembly
.GetEntryAssembly()
.GetReferencedAssemblies()
.Select(Assembly.Load)
.SelectMany(x => x.DefinedTypes)
.Where(type => typeof(IProfile).GetTypeInfo().IsAssignableFrom(type.AsType()));
foreach (var ti in all)
{
var t = ti.AsType();
if (t.Equals(typeof(IProfile)))
{
Mapper.Initialize(cfg =>
{
cfg.AddProfiles(t); // Initialise each Profile classe
});
}
}
}
}
Тепер у веб-проекті MVC Core у файлі Startup.cs у конструкторі виклик класу Mapping, який ініціалізує всі відображення під час завантаження програми.
Mappings.RegisterMappings();
Для ASP.NET Core (тестується з використанням 2.0+ та 3.0), якщо ви бажаєте прочитати вихідну документацію: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md
В іншому випадку виконання цих 4 кроків працює:
Встановіть AutoMapper.Extensions.Microsoft.DependancyInjection з nuget.
Просто додайте кілька профільних класів.
Потім додайте нижче до класу startup.cs.
services.AddAutoMapper(OneOfYourProfileClassNamesHere)
Тоді просто введіть IMapper у свої контролери або там, де вам це потрібно:
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper){
_mapper = mapper;
}
А якщо ви хочете використовувати ProjectTo його зараз просто:
var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
Для AutoMapper 9.0.0:
public static IEnumerable<Type> GetAutoMapperProfilesFromAllAssemblies()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var aType in assembly.GetTypes())
{
if (aType.IsClass && !aType.IsAbstract && aType.IsSubclassOf(typeof(Profile)))
yield return aType;
}
}
}
MapperProfile:
public class OrganizationProfile : Profile
{
public OrganizationProfile()
{
CreateMap<Foo, FooDto>();
// Use CreateMap... Etc.. here (Profile methods are the same as configuration methods)
}
}
У вашому запуску:
services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
.ToArray());
У контролері чи сервісі: Ін'єкційний картограф:
private readonly IMapper _mapper;
Використання:
var obj = _mapper.Map<TDest>(sourceObject);
Щоб додати те, що Arve Systad згадав для тестування. Якщо з будь-якої причини ви схожі на мене і хочете зберегти структуру спадкування, надану в рішенні theutz, ви можете встановити MapperConfiguration так:
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);
Я зробив це в NUnit.
services.AddAutoMapper (); не працювало для мене. (Я використовую Asp.Net Core 2.0)
Після налаштування, як показано нижче
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.CreateMap<ClientCustomer, Models.Customer>();
});
ініціалізувати Mapper IMapper mapper = config.CreateMapper ();
і додайте об’єкт mapper до сервісів як однотонних служб.AddSingleton (mapper);
таким чином я можу додати DI до контролера
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
і я використовував, як показано нижче, у своїх методах дії
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
щодо відповіді theutz, немає необхідності вказувати параметрметра Mapper IMapper у конструкторі контролерів.
ви можете використовувати Mapper, оскільки він є статичним членом у будь-якому місці коду.
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
ви можете знущатися над цим і, наприклад, просто змушувати повернути його до нуля, якщо це не має значення для даного тесту.