如何在ASP中建立Automapper。网络核心

我是。net的新手,所以我决定使用。net Core,而不是学习“老方法”。我找到了一篇关于在这里为。net Core设置AutoMapper的详细文章,但是对于新手来说,有没有更简单的攻略呢?

314910 次浏览

我想明白了!细节如下:

  1. 通过NuGet将主AutoMapper包添加到您的解决方案中。

  2. 通过NuGet将AutoMapper依赖注入包添加到您的解决方案中。

  3. 为映射配置文件创建一个新类。(我在主解决方案目录中创建了一个名为MappingProfile.cs的类,并添加了以下代码。)我将使用UserUserDto对象作为示例。

     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>();
    }
    }
    
  4. 然后在Startup.cs中添加AutoMapperConfiguration,如下所示:

     public void ConfigureServices(IServiceCollection services) {
    // .... Ignore code before this
    
    
    // Auto Mapper Configurations
    var mapperConfig = new MapperConfiguration(mc =>
    {
    mc.AddProfile(new MappingProfile());
    });
    
    
    IMapper mapper = mapperConfig.CreateMapper();
    services.AddSingleton(mapper);
    
    
    services.AddMvc();
    
    
    }
    
  5. 要在代码中调用映射对象,执行如下操作:

     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!
    }
    }
    

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();
}

关于utz的答案, 不需要在控制器的构造函数中指定imap映射器参数

您可以使用Mapper,因为它是代码任何位置的静态成员。

public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}

我使用的是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
});
}
}
}


}
现在在MVC核心web项目的Startup.cs文件中,在构造函数中,调用Mapping类,它将在应用程序时初始化所有映射 装载。< / p >
Mappings.RegisterMappings();

添加到Arve Systad提到的测试中。如果你像我一样,想要维护utz解决方案中提供的继承结构,你可以像这样设置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>();
});
初始化映射器 IMapper mapper = config.CreateMapper();

.

并将mapper对象作为单例添加到服务中 services.AddSingleton(映射);< / p >

这样我就可以添加DI到控制器

  private IMapper autoMapper = null;


public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}

我在我的动作方法中使用了如下

  ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);

我想扩展@theutz的答案-即这一行:

// services.AddAutoMapper(typeof(Startup));  // <-- newer automapper version uses this signature.

AutoMapper.Extensions.Microsoft.DependencyInjection 3.2.0版本有一个错误(可能)。(我使用的是。net Core 2.0)

这是解决 GitHub问题。如果你继承AutoMapper的Profile类存在于你的Startup类所在的程序集之外,如果你的AutoMapper注入是这样的,它们可能不会被注册:

services.AddAutoMapper();

除非您显式指定要搜索AutoMapper概要文件的程序集。

在你的初创公司中也可以这样做。ConfigureServices:

services.AddAutoMapper(<assembies> or <type_in_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已经包含AutoMapper配置文件的JITed程序集,这可能是真的,也可能不是真的,因为它们只在需要时被jit(更多细节在 StackOverflow问题中)。

使用ASP使用AutoMapper。净的核心。

步骤1。从NuGet包中安装AutoMapper.Extensions.Microsoft.DependencyInjection。

enter image description here

步骤2。在“解决方案”中创建一个文件夹以保存名称为“Mappings”的映射。

enter image description here

步骤3。添加映射文件夹后,我们添加了一个名称为“MappingProfile”的类,这个名称可以是唯一的,很好理解。

在本课程中,我们将维护所有映射。

enter image description here

步骤4。在启动“ConfigureServices”时初始化映射器

在启动类,我们需要初始化配置文件,我们已经创建和注册AutoMapper服务。

  Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());


services.AddAutoMapper();

显示ConfigureServices方法的代码片段,其中我们需要初始化和注册AutoMapper。

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);
}
}
< p > ASP。NET Core(使用2.0+和3.0测试),如果你喜欢阅读源文档: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md < / p >

否则,遵循以下4个步骤即可:

  1. 从nuget安装AutoMapper.Extensions.Microsoft.DependancyInjection。

  2. 只需添加一些概要文件类。

  3. 然后添加到你的startup.cs类。 李services.AddAutoMapper(OneOfYourProfileClassNamesHere) < / p > < / >

  4. 然后简单地在你的控制器或任何你需要它的地方注入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()

在我的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
{
...
}

我用这种方式解决了它(类似于上面,但我觉得这是一个更干净的解决方案)。net Core 3.x

创建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);
}
}




Asp。Net Core 2.2与AutoMapper.Extensions.Microsoft.DependencyInjection。

public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Domain, DomainDto>();
}
}

在Startup.cs

services.AddAutoMapper(typeof(List.Handler));

我喜欢很多答案,尤其是@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的类。配置文件(像我的,MappingProfile)。

因此,在我的例子中,类属于同一个正在执行的程序集,服务注册可以缩短为services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(一种更优雅的方法是使用这种编码的无参数扩展)。< / p >

谢谢,卢西恩!

对于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);

在最新版本的asp.net core中,你应该使用以下初始化:

services.AddAutoMapper(typeof(YourMappingProfileClass));

需要安装一个安装自动程序的包。

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; }
}

让我们来看看如何将Auto mapper添加到。net Core应用程序中。

<强>步骤: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层,我们将有一个视图模型来显示用户信息:

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

现在,让我们定义一个Controller并使用我们刚刚添加的Auto-Mapping功能:

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);
}
}
首先,我们将mapper对象注入到控制器中。然后,我们调用Map()方法,它将User对象映射到UserViewModel对象。此外,请注意我们用于本地数据存储的本地方法GetUserDetails。 你可以在我们的源代码中找到它的实现

在.NET 6中,你需要在Program.cs文件中添加以下内容:

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());