Dependency injection 自动映射与依赖项注入

Dependency injection 自动映射与依赖项注入,dependency-injection,automapper,Dependency Injection,Automapper,我目前有以下映射: Mapper.CreateMap<Journal, JournalDto>(); Mapper.CreateMap(); 现在,Journal包含一个名为RefTypeID的成员,该成员对应的值存在于数据库的另一个表中;为了查找这个值,我有一个服务来处理一个简单的int->string请求。automapper配置当前发生在程序开始时的静态类中。将映射代码移动到注入DI容器的类中可以吗?或者有更好的方法吗?下面是我如何解决的: 我定义了一个IMappingCr

我目前有以下映射:

Mapper.CreateMap<Journal, JournalDto>();
Mapper.CreateMap();

现在,
Journal
包含一个名为
RefTypeID
的成员,该成员对应的值存在于数据库的另一个表中;为了查找这个值,我有一个服务来处理一个简单的
int->string
请求。automapper配置当前发生在程序开始时的静态类中。将映射代码移动到注入DI容器的类中可以吗?或者有更好的方法吗?

下面是我如何解决的:

我定义了一个
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));
        }
    }

这使得初始设置非常容易,因为所有的创建都发生在一个地方,并且您可以拥有任意多的映射创建者(但是,您应该将这些创建者保持在最低限度,可能每个项目一次左右,获取所有需要的服务来映射该项目中的特定类型).

您可以依赖于
IMappingEngine
,而不是使用静态类
Mapper


这里有一篇很好的博客文章:

更好的方法是使用客户解析器。映射配置是静态的,因此自定义解析器旨在为单个成员提供映射:

Mapper.Initialize(cfg=>{
ConstructServicesUsing(type=>whatevermefussestogetInstances.GetInstance(type));
cfg.CreateMap()
.FormMember(dest=>dest.RefTypeName,
opt=>opt.resolvesusing());
});
然后,您的解析器变成:

[导出(typeof(IRefTypeNameResolver))]
公共类RefTypeNameResolver:ValueResolver、IRefTypeNameResolver
{
专用只读IRefTypesLookup IRefTypesLookup;
[导入构造函数]
公共RefTypeNameResolver(IRefTypesLookup rtl)
{
iRefTypesLookup=rtl;
}
受保护的重写字符串ResolveCore(日志源)
{
返回iRefTypesLookup.Lookup(source.RefTypeID);
}
}

配置需要执行一次,这就是为什么配置API提供执行API的挂钩(类型转换器、值解析器等)

这里是最新的执行方式


虽然我个人将自动映射添加到控制器中,但没有添加到存储库中。通过这种方式,您可以为不同的控制器使用相同的存储库,并具有不同的映射。不过,同样的概念是,只需将
IMapper
注入控制器而不是存储库。

我认为不这样做的唯一原因纯粹是组织性的。您的项目中可能都有映射代码。如果域对象发生更改或DTO可能不理想。但是我很想从其他人那里了解他们的观点。好吧,我仍然会把映射代码保存在一个地方——比如,那个类,它会从DI容器中获取所有需要的服务。我只需要自己初始化映射,而不是依靠静态构造函数自动执行它。。。我可能得从这里借钱!:D MEF是对框架的一个很好的补充。请放心,我不认为我是唯一遇到这个问题的人。我知道ValueResolver,但我认为它们没有用,因为我错过了使用配置的ConstructionServices。不错!
    var mappings = container.GetExportedValues<IMappingCreator>();

    foreach (IMappingCreator mc in mappings)
    {
        mc.CreateMappings();
    }