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


我想明白了!细节如下:

Add the main AutoMapper Package to your solution via NuGet. Add the AutoMapper Dependency Injection Package to your solution via NuGet. Create a new class for a mapping profile. (I made a class in the main solution directory called MappingProfile.cs and add the following code.) I'll use a User and UserDto object as an example. 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>(); } } Then add the AutoMapperConfiguration in the Startup.cs as shown below: 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(); } To invoke the mapped object in code, do something like the following: 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();
}

关于这个问题的答案, 不需要在控制器构造函数中指定IMapper映射器参数。

您可以使用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类,它将在应用程序时初始化所有映射 装载。

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(映射);

这样我就可以添加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>);

其中"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。

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

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

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

步骤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);
        }
    }

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

在我的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()); (一种更优雅的方法是使用这种编码的无参数扩展)。

谢谢,卢西恩!


对于自动映射器 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));

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

添加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);
    }
}

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


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

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

对于使用。net 7的AutoMapper 11.0.1,我开始得到这个异常:

System.ArgumentException: 'GenericArguments[0], 'System.DateTime', on 'T MaxInteger[T](System.Collections.Generic.IEnumerable`1[T])' violates the constraint of type 'T'.'

Inner Exception
VerificationException: Method System.Linq.Enumerable.MaxInteger: type argument 'System.DateTime' violates the constraint of type parameter 'T'.

看这个问题:

系统。DateTime on 'T MaxInteger[T](System.Collections.Generic.IEnumerable ' 1[T])'违反了。net 7使用AutoMapper 11.0.1的T类型约束

这意味着我不能再使用services.AddAutoMapper(typeof(MappingProfile).Assembly);无一例外。

对于AutoMapper.Extensions.Microsoft.DependencyInjection我这样解决它:

services.AddAutoMapper(cfg => cfg.Internal().MethodMappingEnabled = false, typeof(MappingProfile).Assembly);

对于Blazor WebAssembly客户端,解决方案是这样的:

var mapperConfig = new MapperConfiguration(mc =>
{
    //Needed for https://github.com/AutoMapper/AutoMapper/issues/3988
    mc.Internal().MethodMappingEnabled = false;
    mc.AddProfile(new MappingProfile());
});
//mapperConfig.AssertConfigurationIsValid();

IMapper mapper = mapperConfig.CreateMapper();
builder.Services.AddSingleton(mapper);