Automapper与依赖注入一起使用

Fem*_*ref 21 dependency-injection automapper

我目前有以下映射:

Mapper.CreateMap<Journal, JournalDto>();
Run Code Online (Sandbox Code Playgroud)

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

Jim*_*ard 16

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

Mapper.Initialize(cfg => {
    cfg.ConstructServicesUsing(type => WhateverMefUsesToGetInstances.GetInstance(type));

    cfg.CreateMap<Journal, DisplayJournal>()
        .ForMember(dest => dest.RefTypeName, 
            opt => opt.ResolveUsing<RefTypeNameResolver>());
});
Run Code Online (Sandbox Code Playgroud)

然后你的解析器变成:

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Mar*_*R-L 14

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

这里有一篇很好的博客文章:使用依赖注入模拟AutoMapper


Fem*_*ref 9

这是我解决它的方式:

我定义了一个IMappingCreator接口:

public interface IMappingCreator
{
  void CreateMappings();
}
Run Code Online (Sandbox Code Playgroud)

我继续实现了一个带有该接口的类(我使用MEF作为DI容器,这是属性的来源),它被放入DI容器中IMappingCreator:

[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));
        }
    }
Run Code Online (Sandbox Code Playgroud)

最后,在我的应用程序启动时,我在容器中获取该接口的所有实例并调用CreateMappings它们上的方法:

    var mappings = container.GetExportedValues<IMappingCreator>();

    foreach (IMappingCreator mc in mappings)
    {
        mc.CreateMappings();
    }
Run Code Online (Sandbox Code Playgroud)

这使得初始设置非常简单,因为所有创建都在一个地方进行,并且您可以拥有任意数量的地图创建者(但是,您应该将这些设置保持在最低限度,可能每个项目左右一次,抓住所有需要的服务用于映射该项目中的特定类型).


Gen*_*e S 5

这是最新的方法...

https://pintoservice.wordpress.com/2016/01/31/dependency-injection-for-automapper-4-2-in-asp-net-vnext-mvc-project/

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