我目前有以下映射:
Mapper.CreateMap<Journal, JournalDto>();
现在,Journal
包含一个名为RefTypeID
的成员,其对应的值存在于数据库的另一个表中;为了查找这个值,我有一个处理简单int -> string
请求的服务。 automapper配置当前发生在程序开始时的静态类中。是否可以将映射代码移动到一个被注入我的DI容器的类中,或者有更好的方法吗?
答案 0 :(得分:15)
更好的方法是使用客户解析器。映射配置是静态的,因此自定义解析器旨在为单个成员提供映射:
Mapper.Initialize(cfg => {
cfg.ConstructServicesUsing(type => WhateverMefUsesToGetInstances.GetInstance(type));
cfg.CreateMap<Journal, DisplayJournal>()
.ForMember(dest => dest.RefTypeName,
opt => opt.ResolveUsing<RefTypeNameResolver>());
});
然后你的解析器变成:
[Export(typeof(IRefTypeNameResolver))]
public class RefTypeNameResolver : ValueResolver<Journal, string>, IRefTypeNameResolver
{
private readonly IRefTypesLookup iRefTypesLookup;
[ImportingConstructor]
public RefTypeNameResolver (IRefTypesLookup rtl)
{
iRefTypesLookup = rtl;
}
protected override string ResolveCore(Journal source)
{
return iRefTypesLookup.Lookup(source.RefTypeID);
}
}
配置需要执行一次,这就是配置API为执行API(类型转换器,值解析器等)提供挂钩的原因。
答案 1 :(得分:14)
您可以依赖IMappingEngine
而不是使用静态类Mapper
。
这里有一篇很好的博客文章:Mocking out AutoMapper with Dependency Injection
答案 2 :(得分:9)
以下是我解决它的方法:
我定义了IMappingCreator
界面:
public interface IMappingCreator
{
void CreateMappings();
}
我继续实现了一个带有该接口的类(我使用MEF作为DI容器,这是属性的来源),它作为IMappingCreator
放入DI容器中:
[Export(typeof(IMappingCreator))]
public class Mapping : IMappingCreator
{
private readonly IRefTypesLookup iRefTypesLookup;
[ImportingConstructor]
public Mapping(IRefTypesLookup rtl)
{
iRefTypesLookup = rtl;
}
public void CreateMappings()
{
Mapper.CreateMap<Journal, DisplayJournal>().AfterMap((j, dj) => dj.RefTypeName = iRefTypesLookup.Lookup(j.RefTypeID));
}
}
最后,在我的应用程序启动中,我在容器中获取该接口的所有实例,并在其上调用CreateMappings
方法:
var mappings = container.GetExportedValues<IMappingCreator>();
foreach (IMappingCreator mc in mappings)
{
mc.CreateMappings();
}
这使得初始设置非常简单,因为所有创建都在一个地方进行,并且您可以拥有任意数量的地图创建者(但是,您应该将这些设置保持在最低限度,可能每个项目一次左右,抓住用于映射该项目中特定类型的所有必需服务。)
答案 3 :(得分:2)
这是最新的做法......
虽然我个人在控制器中添加自动映射,但不在存储库中。这样,您可以为不同的控制器使用相同的存储库,并具有不同的映射。但是,相同的概念,只需在控制器而不是存储库中注入IMapper
。