我发现了AutoMapper的一些非常奇怪的行为。 这个简单的代码
internal class Program
{
private static void Main(string[] args)
{
Mapper.Initialize(cfg => { cfg.CreateMap<MyClass1, MyClass2>(); });
Mapper.Initialize(cfg => { cfg.CreateMap<MyClass3, MyClass4>(); });
var dto = new MyClass1();
Mapper.Map<MyClass1, MyClass2>(dto);
}
}
public class MyClass1
{
}
public class MyClass2
{
}
public class MyClass3
{
}
public class MyClass4
{
}
生成异常:
缺少类型映射配置或不支持的映射。
映射类型:MyClass1 - &gt; MyClass2 ConsoleApplication2.MyClass1 - &gt; ConsoleApplication2.MyClass2
但是如果改变两个初始化行的顺序,就像这样
Mapper.Initialize(cfg => { cfg.CreateMap<MyClass3, MyClass4>(); });
Mapper.Initialize(cfg => { cfg.CreateMap<MyClass1, MyClass2>(); });
一切都很好。怎么了?发生了什么事?
答案 0 :(得分:2)
长话短说,Jimmy 暂时远离AutoMapper中的静态内容,转而使用基于实例的映射。然而,正如吉米评论的那样:
静态映射器不会被删除,只能在代码中的任何地方调用CreateMap
质疑错误的答案是你试图初始化两次,而不是一次。
要回答有关如何在代码中分散不同配置的下一个问题,请使用Profile
要回答如何配置所有内容,请参阅以下内容:
有一个MapperConfigurationExpression
您可以传递给映射器,或Mapper
获取Action<IMapperConfigurationExpression>
。
IMapperConfigurationExpression
暴露了这个:
void AddProfile(Profile profile)
所以你几乎可以像下面这样做,但是在IMapper
接口上注册所有内容,这就像4.2.1
正朝着这样做。
以下是一个示例配置文件:
using AutoMapper;
using TreasuryRecords.Database.Models;
using TreasuryRecords.Requests.Account.Models;
public class AccountMappings : Profile
{
protected override void Configure()
{
this.CreateMap<RegisterDto, Client>()
.ForMember(x => x.UserName, c => c.MapFrom(x => x.Email));
}
}
以下是我如何注册个人资料的示例:
using System;
using System.Linq;
using System.Reflection;
using AutoMapper;
using TreasuryRecords.Requests.Authenticate.Login;
public static class AutoMapperConfig
{
public static void Configure()
{
Assembly
.GetExecutingAssembly()
.RegisterConfigurations();
typeof(LoginRequest)
.Assembly
.RegisterConfigurations();
}
public static void RegisterConfigurations(this Assembly assembly)
{
var types = assembly.GetTypes();
var automapperProfiles = types
.Where(x => typeof(Profile).IsAssignableFrom(x))
.Select(Activator.CreateInstance)
.OfType<Profile>()
.ToList();
// so here you can pass in the instance of mapper
// I just use the static for ease
automapperProfiles.ForEach(Mapper.Configuration.AddProfile);
}
}
这是我将它添加到DI的方式:
public static void RegisterAutoMapper(this IUnityContainer container)
{
container.RegisterType<IMapper>(new InjectionFactory(_ => Mapper.Instance));
}
我在这里使用了unity,但这非常简单,只需在接口Mapper.Instance
上注册IMapper
。
然后我注入IMapper
并像这样使用它:
this.mapper.Map<Client>(message.RegistrationDetails);