14.AutoMapper 之依赖注入(Dependency Injection)

依赖注入(Dependency Injection)

AutoMapper支持使用静态服务定位构建自定义值解析器和自定义类型转换器的功能:

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

    cfg.CreateMap<Source, Destination>();
});

或者在基于实例的容器(包括子/嵌套容器)中使用动态服务定位:

var mapper = new Mapper(Mapper.Configuration, childContainer.GetInstance);

var dest = mapper.Map<Source, Destination>(new Source { Value = 15 });

陷阱

使用IQueryable.ProjectTo扩展方法与使用依赖注入是互斥的。请使用
IEnumerable.Select(_mapper.Map<DestinationType>).ToList() 来代替IQueryable.ProjectTo

ASP.NET Core

有一个NuGet包与这里描述的默认注入机制搭配使用。

Ninject

对于那些使用Ninject的人来说,这有一个AutoMapper使用的Ninject模块的例子

public class AutoMapperModule : NinjectModule
{
    public override void Load()
    {
        Bind<IValueResolver<SourceEntity, DestModel, bool>>().To<MyResolver>();

        var mapperConfiguration = CreateConfiguration();
        Bind<MapperConfiguration>().ToConstant(mapperConfiguration).InSingletonScope();

        // This teaches Ninject how to create automapper instances say if for instance
        // MyResolver has a constructor with a parameter that needs to be injected
        Bind<IMapper>().ToMethod(ctx =>
             new Mapper(mapperConfiguration, type => ctx.Kernel.Get(type)));
    }

    private MapperConfiguration CreateConfiguration()
    {
        var config = new MapperConfiguration(cfg =>
        {
            // Add all profiles in current assembly
            cfg.AddProfiles(GetType().Assembly);
        });

        return config;
    }
}

简单注入器实现

工作流程如下:

  1. 通过 MyRegistrar.Register注册你的类型
  2. MapperProvider允许你直接将IMapper的实例注入到其他类中
  3. SomeProfile使用PropertyThatDependsOnIocValueResolver解析值
  4. PropertyThatDependsOnIocValueResolverIService注入其中

ValueResolver能访问IService,是因为我们通过MapperConfigurationExpression.ConstructServicesUsing注册容器。

public class MyRegistrar
{
    public void Register(Container container)
    {
        // Injectable service
        container.RegisterSingleton<IService, SomeService>();

        // Automapper
        container.RegisterSingleton(() => GetMapper(container));
    }

    private AutoMapper.IMapper GetMapper(Container container)
    {
        var mp = container.GetInstance<MapperProvider>();
        return mp.GetMapper();
    }
}

public class MapperProvider
{
    private readonly Container _container;

    public MapperProvider(Container container)
    {
        _container = container;
    }

    public IMapper GetMapper()
    {
        var mce = new MapperConfigurationExpression();
        mce.ConstructServicesUsing(_container.GetInstance);

        var profiles = typeof(SomeProfile).Assembly.GetTypes()
            .Where(t => typeof(Profile).IsAssignableFrom(t))
            .ToList();

        mce.AddProfiles(profiles);

        var mc = new MapperConfiguration(mce);
        mc.AssertConfigurationIsValid();

        IMapper m = new Mapper(mc, t => _container.GetInstance(t));

        return m;
    }
}

public class SomeProfile : Profile
{
    public SomeProfile()
    {
        var map = CreateMap<MySourceType, MyDestinationType>();
        map.ForMember(d => d.PropertyThatDependsOnIoc, opt => opt.ResolveUsing<PropertyThatDependsOnIocValueResolver>());
    }
}

public class PropertyThatDependsOnIocValueResolver : IValueResolver<MySourceType, object, int>
{
    private readonly IService _service;

    public PropertyThatDependsOnIocValueResolver(IService service)
    {
        _service = service;
    }

    int IValueResolver<MySourceType, object, int>.Resolve(MySourceType source, object destination, int destMember, ResolutionContext context)
    {
        return _service.MyMethod(source);
    }
}

推荐阅读更多精彩内容

  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 12,000评论 6 85
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 41,213评论 11 349
  • 一、概念解释 使用 .NET,通过 new 运算符(即,new MyService 或任何想要实例化的对象类型)调...
    不是隔壁的老王啊阅读 1,490评论 0 0
  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,434评论 0 11
  • 虽已放假,但还是放几张我学校的图吧~ 这是考四六级那天,天气好的不像话 我从宝龙广场出来,没多久就下雨了 大一下,...
    酒窝ya阅读 237评论 0 0
  • 大概也只有早高峰的时刻,城市才更有城市的样子。 上班的上班,上学的上学,匆匆忙忙地赶赴目的地。大概谁也不会注意到,...
    米姆一家阅读 58评论 0 0
  • 八千零叁拾伍天前的我: 快乐吗?骄傲吗?后悔吗?如果你知道现在的我在未来会是这个鬼样子,该是什么样的鬼心情呢? 嗨...
    笠也阅读 128评论 0 1