我在 .NET 方面相对较新,我决定解决 .NET Core 而不是学习“旧方法”。我找到了一篇关于 setting up AutoMapper for .NET Core here 的详细文章,但是对于新手有没有更简单的演练?
我想到了!这是详细信息:
通过 NuGet 将主 AutoMapper 包添加到您的解决方案中。通过 NuGet 将 AutoMapper 依赖注入包添加到您的解决方案中。为映射配置文件创建一个新类。 (我在主解决方案目录中创建了一个名为 MappingProfile.cs 的类并添加了以下代码。)我将使用 User 和 UserDto 对象作为示例。 public class MappingProfile : Profile { public MappingProfile() { // 添加尽可能多的这些行来映射您的对象 CreateMap
将 AutoMapper 与 ASP.NET Core 一起使用的步骤。
步骤 1. 从 NuGet 包安装 AutoMapper.Extensions.Microsoft.DependencyInjection。
https://i.stack.imgur.com/NLEBL.png
步骤 2. 在解决方案中创建一个文件夹以保留名称为“映射”的映射。
https://i.stack.imgur.com/6wOpQ.png
步骤 3. 添加 Mapping 文件夹后,我们添加了一个名为“MappingProfile”的类,该名称可以是任何独特且易于理解的名称。
在本课程中,我们将维护所有映射。
https://i.stack.imgur.com/GSeup.png
步骤 4. 在启动“ConfigureServices”中初始化 Mapper
在启动类中,我们需要初始化我们创建的配置文件并注册 AutoMapper 服务。
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
代码片段显示我们需要初始化和注册 AutoMapper 的 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);
代码片段
[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)
这在 this GitHub 问题中得到解决。如果您的继承 AutoMapper 的 Profile 类的类存在于您的 Startup 类所在的程序集之外,如果您的 AutoMapper 注入如下所示,则它们可能不会被注册:
services.AddAutoMapper();
除非您明确指定要搜索 AutoMapper 配置文件的程序集。
可以在您的 Startup.ConfigureServices 中这样做:
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
其中“assemblies”和“type_in_assemblies”指向在您的应用程序中指定 Profile 类的程序集。例如:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
我假设(我强调这个词)是由于以下无参数重载的实现(来自 GitHub 的源代码):
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
我们依赖 CLR 已经 JITed 程序集,其中包含 AutoMapper 配置文件,这些配置文件可能是也可能不是真的,因为它们只在需要时才被 jit(更多细节在 this 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 3.x
创建 MappingProfile.cs 类并使用 Maps 填充构造函数(我计划使用单个类来保存我的所有映射)
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Dest>().ReverseMap();
}
}
在 Startup.cs 中,添加以下内容以添加到 DI(程序集 arg 用于保存映射配置的类,在我的情况下,它是 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);
}
}
AutoMapper.Extensions.Microsoft.DependencyInjection
services.AddScoped<IMapper, Mapper>();
,IMapper 是 AutoMapper 接口,Mapper 来自 AutoMapper,所以我们不需要做任何事情
在最新版本的 asp.net core 中,您应该使用以下初始化:
services.AddAutoMapper(typeof(YourMappingProfileClass));
services.AddAutoMapper(Assembly.GetExecutingAssembly());
获取从该程序集中的 Profile 类派生的所有映射类。
我喜欢很多答案,尤其是@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();
}
}
- - - 编辑 - - -
在阅读了 Lucian Bargaoanu 评论中链接的文档后,我认为最好稍微改变一下这个答案。
无参数的 services.AddAutoMapper()
(有@saineshwar 的答案)不再起作用(至少对我而言)。但是,如果您使用 NuGet 程序集 AutoMapper.Extensions.Microsoft.DependencyInjection,该框架能够检查所有扩展 AutoMapper.Profile 的类(例如我的 MappingProfile)。
因此,在我的例子中,如果类属于同一个执行程序集,则服务注册可以缩短为 services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(更优雅的方法可能是使用此编码进行无参数扩展)。
谢谢,卢锡安!
在我的 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) });
?
对于 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;
}
}
}
映射器简介:
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);
需要安装一个包来设置自动映射器。
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection
之后 AddAutoMapper 将在服务中可用。
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper(typeof(Startup));
}
创建从 Employee 类到 EmployeeDTO 的映射器。
using AutoMapper;
public class AutomapperProfile: Profile
{
public AutomapperProfile()
{
//Source to destination.
CreateMap<Employee,EmployeeDTO>();
}
}
EmployeeController 从 Employee 映射到 EmployeeDTo
using System.Collections.Generic;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController()]
public class EmployeeController : ControllerBase
{
private readonly IMapper _mapper;
public EmployeeController(IMapper mapper)
{
_mapper = mapper;
}
[HttpGet]
public IEnumerable<EmployeeDTO> GetEmployees()
{
/*
Assume it to be a service call/database call
it returns a list of employee, and now we will map it to EmployeeDTO
*/
var employees = Employee.SetupEmployee();
var employeeDTO = _mapper.Map<IEnumerable<EmployeeDTO>>(employees);
return employeeDTO;
}
}
Employee.cs 供参考
using System.Collections.Generic;
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public int Salary { get; set; }
public static IEnumerable<Employee> SetupEmployee()
{
return new List<Employee>()
{
new Employee(){EmployeeId = 1, EmployeeName ="First", Salary=10000},
new Employee(){EmployeeId = 2, EmployeeName ="Second", Salary=20000},
new Employee(){EmployeeId = 3, EmployeeName ="Third", Salary=30000},
new Employee(){EmployeeId = 4, EmployeeName ="Fourth", Salary=40000},
new Employee(){EmployeeId = 5, EmployeeName ="Fifth", Salary=50000}
};
}
}
EmployeeDTO.cs 供参考
public class EmployeeDTO
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
}
我正在使用 AutoMapper 6.1.1 和 asp.net Core 1.1.2。
首先,定义Automapper的Profile Class继承的Profile类。我创建了一个空的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
});
}
}
}
}
现在在 Startup.cs 文件的 MVC Core Web 项目中,在构造函数中调用 Mapping 类,该类将在应用程序加载时初始化所有映射。
Mappings.RegisterMappings();
对于 ASP.NET Core(使用 2.0+ 和 3.0 测试),如果您更喜欢阅读源文档:https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md
否则,请遵循以下 4 个步骤:
从 nuget 安装 AutoMapper.Extensions.Microsoft.DependancyInjection。只需添加一些配置文件类。然后将以下内容添加到您的 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()
让我们看看如何将 Auto mapper 添加到我们的 .NET Core 应用程序中。
step: 1 第一步是安装对应的NuGet包:
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
第2步
安装所需的软件包后,下一步是配置服务。让我们在 Startup.cs 类中进行:
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper(typeof(Startup));
services.AddControllersWithViews();
}
步骤:3
让我们开始使用我们有一个名为 User 的域对象:
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Address { get; set; }
}
在 UI 层,我们将有一个 View Model 来显示用户信息:
public class UserViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
第4步
组织映射配置的一个好方法是使用 Profiles。我们需要创建继承自 Profile 类的类并将配置放入构造函数中:
public UserProfile()
{
CreateMap<User, UserViewModel>();
}
步数:5
现在,让我们定义一个控制器并使用我们刚刚添加的自动映射功能:
public class UserController : Controller
{
private readonly IMapper _mapper;
public UserController(IMapper mapper)
{
_mapper = mapper;
}
public IActionResult Index()
{
// Populate the user details from DB
var user = GetUserDetails();
UserViewModel userViewModel = _mapper.Map<UserViewModel>(user);
return View(userViewModel);
}
}
首先,我们将映射器对象注入控制器。然后,我们调用 Map() 方法,该方法将 User 对象映射到 UserViewModel 对象。此外,请注意我们用于本地数据存储的本地方法 GetUserDetails。您可以在我们的源代码中找到它的实现。
在 .NET 6 中,您需要将以下内容添加到 Program.cs 文件中:
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
带有 AutoMapper.Extensions.Microsoft.DependencyInjection 的 Asp.Net Core 2.2。
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Domain, DomainDto>();
}
}
在 Startup.cs
services.AddAutoMapper(typeof(List.Handler));
services.AddAutoMapper();对我不起作用。 (我使用的是 Asp.Net Core 2.0)
如下配置后
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.CreateMap<ClientCustomer, Models.Customer>();
});
初始化映射器 IMapper mapper = config.CreateMapper();
并将映射器对象作为单例添加到服务中 services.AddSingleton(mapper);
这样我就可以将 DI 添加到控制器
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
我在我的行动方法中使用如下
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
添加到 Arve Systad 提到的测试内容。如果出于某种原因您像我一样想要维护 theutz 解决方案中提供的继承结构,您可以像这样设置 MapperConfiguration:
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);
我在 NUnit 中做到了这一点。
关于 theutz answer ,无需在控制器构造函数中指定 IMapper 映射器参数。
您可以使用 Mapper,因为它是代码任何位置的静态成员。
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
,您可以模拟它,例如,如果它与给定的测试无关,则让它返回 null。
不定期副业成功案例分享
Profile
类的位置