• 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);
        }
    }
    

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

  • 相关阅读:
    鸡哥的限币令(有上下限的网络流/费用流问题)
    AtCoder Regular Contest 128 部分题题解
    一道题
    2021CCPC河南省赛
    10.26训练赛
    博弈论和SG函数
    10.24训练赛
    10.22训练赛
    CF #749
    atcoder ABC233
  • 原文地址:https://www.cnblogs.com/zengpeng/p/11059952.html
Copyright © 2020-2023  润新知