zoukankan      html  css  js  c++  java
  • 14.AutoMapper 之依赖注入(Dependency Injection)

    https://www.jianshu.com/p/f66447282780

     

    依赖注入(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);
        }
    }
    

    码字不易,动动手指给个赞吧

  • 相关阅读:
    Android MediaPlayer
    MediaPlayer基本使用方式
    css 透明度 一句话搞定透明背景!
    CSS ZOOM 作用[IE6下清除浮动]
    document.execcommand方法
    让position:fixed在IE6下可用
    CSS文档流与块级元素(block)内联元素(inline)那点事
    Android屏幕分辨率详解(VGA、HVGA、QVGA、WVGA、WQVGA)
    重载的乐趣
    线程间调用不同线程创建的控件
  • 原文地址:https://www.cnblogs.com/zengpeng/p/11059952.html
Copyright © 2011-2022 走看看