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


当前回答

我想扩展@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问题中)。

其他回答

我想明白了!细节如下:

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

我用这种方式解决了它(类似于上面,但我觉得这是一个更干净的解决方案)。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);
        }
    }


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

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

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

services.AddAutoMapper(typeof(YourMappingProfileClass));