我目前有以下映射:
Mapper.CreateMap<Journal, JournalDto>();
现在,Journal
包含一个名为RefTypeID
的成员,对应的值存在于数据库的另一个表中;为了查找这个值,我有一个服务来处理一个简单的int -> string
请求。自动映射器配置当前发生在程序开始时的静态类中。是否可以将映射代码移动到注入到DI容器的类中,或者是否有更好的方法?
发布于 2010-11-18 08:41:47
下面是我解决这个问题的方法:
我定义了一个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();
}
这使得初始设置变得非常简单,因为所有的创建都发生在一个地方,并且您可以有尽可能多的映射创建器(但是,您应该保持最少的映射创建器,可能每个项目一次左右,获取映射该项目中特定类型所需的所有服务)。
发布于 2011-12-13 21:35:53
更好的方法是使用客户解析器。映射配置是静态的,因此自定义解析器旨在为单个成员提供映射:
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 (类型转换器、值解析器等)的钩子。
发布于 2011-12-12 23:23:26
您可以依赖于IMappingEngine
而不是使用静态类Mapper
。
这里有一篇很好的博客文章:Mocking out AutoMapper with Dependency Injection
https://stackoverflow.com/questions/4204664
复制相似问题