我已经在.Net应用中使用Automapper和Autofac一段时间了。我用这种方式配置它们:
builder.RegisterAssemblyTypes(typeof (OneOfMyMappingProfiles).Assembly)
.Where(t => t.IsSubclassOf(typeof (Profile)))
.As<Profile>();
builder.Register(ctx => new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers))
.AsImplementedInterfaces()
.SingleInstance()
.OnActivating(x =>
{
foreach (var profile in x.Context.Resolve<IEnumerable<Profile>>())
{
x.Instance.AddProfile(profile);
}
});
builder.RegisterType<MappingEngine>()
.As<IMappingEngine>().SingleInstance();
使用最新版本的Automapper(4.2),API已发生变化,我无法转换为新的API。 ConfigurationStore似乎不再存在。根据文件,注册IOC的方式现在是这样的:
var profiles =
from t in typeof (AutoMapperRegistry).Assembly.GetTypes()
where typeof (Profile).IsAssignableFrom(t)
select (Profile)Activator.CreateInstance(t);
var config = new MapperConfiguration(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
});
For<MapperConfiguration>().Use(config);
For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));
但是正在使用StructureMap。上半部分没有问题,但我不知道如何翻译“For&lt;&gt; .Use()”部分。我如何在Autofac中做到这一点?
答案 0 :(得分:18)
行。解决了这个问题。这是替代品:
var profiles =
from t in typeof(LocationMappingProfile).Assembly.GetTypes()
where typeof(Profile).IsAssignableFrom(t)
select (Profile)Activator.CreateInstance(t);
builder.Register(ctx => new MapperConfiguration(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
}));
builder.Register(ctx => ctx.Resolve<MapperConfiguration>().CreateMapper()).As<IMapper>();
<强>更新强>
以下是个人资料的示例。超级简单。在这种情况下,我只有一个映射。但我可以添加其他人。我尝试通过实体将它们逻辑地保持在一起。因此,在这种情况下,从ProviderDetail到ProviderDetail的任何未来映射都将在此文件中。映射到不同的实体将位于单独的mappingprofile类中。配置文件类中没有注入任何内容:
public class ProviderMappingProfile : Profile
{
protected override void Configure()
{
CreateMap<ProviderDetail, ProviderListItem>();
}
}
<强> UPDATE2 强>
以下是一个证明映射正确的测试示例:
public class ProviderMappingProfileTests
{
[Fact]
public void CreateMap_ProviderDetailToProviderQueryResult_IsValid()
{
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<ProviderDetail, ProviderListItem>()
);
config.AssertConfigurationIsValid();
}
}
答案 1 :(得分:4)
通过Autofac注册Automapper的另一种有趣方法,即动态注册程序集中的所有自定义配置文件。
在这里,您可以为所需的所有装配注册配置文件。
builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(Program)))
.Where(t => t.BaseType == typeof(Profile)
&& !t.IsAbstract && t.IsPublic)
.As<Profile>();
在这里解决这些问题:
builder.Register(ctx => new MapperConfiguration(cfg =>
{
foreach (var profile in ctx.Resolve<IEnumerable<Profile>>())
cfg.AddProfile(profile);
}));
builder.Register(ctx => ctx.Resolve<MapperConfiguration>()
.CreateMapper())
.As<IMapper>()
.SingleInstance();
另外,可以使用
.CreateMapper(ctx.Resolve)
而不是
.CreateMapper()
解决配置文件中的内部依赖关系。但它需要删除
.SingleInstance()
来自注册。
以下是BTW的用法:
public SomeAutowiredClass
{
public IMapper Mapper { get; set; }
public void SomeMethod(SomeModel model){
Mapper.Map<AnotherModel>(model)
}
}
答案 2 :(得分:2)
我同意上述解决方案。我们不能在下面使用反射吗?
public static IMapper RegisterAutoMapper()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<ApiMappingProfile1>();
cfg.AddProfile<ApiMappingProfile2>();
// Add all your profiles
});
var mapper = config.CreateMapper();
return mapper;
}
在Autofac注册
builder.Register(c => AutoMapperConfig.RegisterAutoMapper()).As<IMapper>()
.InstancePerLifetimeScope().PropertiesAutowired().PreserveExistingDefaults();
答案 3 :(得分:0)
这是一个小修改,对我有用。它会扫描所有已加载的程序集并从中加载所有AutoMapper配置文件。
<script>
var played = moment.duration('{{ $ArenaLastGameTimePlayed }}'); //PT8M10.9525157S
//console.log(played);
$("#time").append( "<b>" + played.humanize() + "</b>");
</script>
它需要过滤抽象和私有类以跳过内置的AutoMapper。