如何使用Simple Injector注册AutoMapper 4.2.0

已更新至AutoMapper 4.2.0,并按照此处提供的迁移指南进行操作: https : //github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API/f4784dac61b91a0df130e252c91a0efd76ff51de#preserving-static-feel 。 尝试将StructureMap的页面上的代码转换为Simple Injector。 有人能告诉我这个代码在Simple Injector中的样子吗?

StructureMap

public class AutoMapperRegistry : Registry { public AutoMapperRegistry() { var profiles = from t in typeof (AutoMapperRegistry).Assembly.GetTypes() where typeof (Profile).IsAssignableFrom(t) select (Profile)Activator.CreateInstance(t); var config = new MapperConfiguration(cfg => { foreach (var profile in profiles) { cfg.AddProfile(profile); } }); For().Use(config); For().Use(ctx => ctx.GetInstance().CreateMapper(ctx.GetInstance)); } } 

简单的注射器

 ? 

这相当于:

 container.RegisterSingleton(config); container.Register(() => config.CreateMapper(container.GetInstance)); 

Simple Injector的IPackage接口看起来就像StructureMap的Registry类型一样。 这是我使用的包,来自@ Steven的回答 :

 using System; using System.Linq; using System.Reflection; // using AutoMapper; // using SimpleInjector; using SimpleInjector.Packaging; public class AutoMapperPackage : IPackage { public void RegisterServices(Container container) { var profiles = Assembly.GetExecutingAssembly() .GetTypes() .Where(x => typeof(AutoMapper.Profile).IsAssignableFrom(x)); var config = new MapperConfiguration(cfg => { foreach (var profile in profiles) { cfg.AddProfile(Activator.CreateInstance(profile) as AutoMapper.Profile); } }); container.RegisterSingleton(config); container.Register(() => config.CreateMapper(container.GetInstance)); } } 

您需要添加SimpleInjector.Packaging包,然后添加对container.RegisterPackages();的调用container.RegisterPackages(); 在你的bootstrap /配置代码中。

从本质上讲,唯一真正从StructureMap改变的是最后两行。

为了映射具有不同MapperConfiguration对象的多个IMapper,这似乎是一个有些反复出现的问题,我推荐以下方法,它甚至不需要重构mapper方法调用:

1)围绕IMapper接口创建通用包装器。 这个包装器可以是一个接口或类,但显然你最终必须实现你的包装器,所以我将在下面展示具体的类。 有这个包装器实现(或inheritance,如果你选择创建一个接口)IMapper接口,如下所示:

 public class ProfileMapper : IMapper where TProfile : Profile { private IMapper mapper; private Profile profile; public ProfileMapper(TProfile profile) { this.profile = profile; this.mapper = new MapperConfiguration( cfg => cfg.AddProfile( this.profile ) ) .CreateMapper(); } } 

generics参数必须是“Profile”的子类,因为从该配置文件开始,您将获得映射器配置。

2)在这个类中,简单地通过将调用重定向到您在构造函数中创建的私有IMapper实例来实现IMapper接口,如下所示:

 public TDestination Map(object source) { return mapper.Map( source ); } 

3)现在,您需要在Simple Injector中为您拥有的每个配置文件注册此ProfileMapper类的部分关闭实例。 首先,通过获取从Profileinheritance的所有类,然后创建此部分关闭的实例,然后注册它。 有几种获取所有Profile类的方法,但我接受了这个:

  IEnumerable profileRegistrations = from type in profileAssembly.GetExportedTypes() where type.Namespace == "Namespace.Of.My.Profiles" where type.BaseType.Equals( typeof( Profile ) ) select type; foreach (Type profileType in profileRegistrations) { Container.RegisterSingleton( profileType, profileType ); Type mapperClosedType = typeof( ProfileMapper<> ).MakeGenericType( profileType ); Container.RegisterSingleton( typeof( ProfileMapper<> ), mapperClosedType ); } 

此代码首先获取从Profile中inheritance的所有类型,位于所述命名空间中。 然后对于每个Profile,我用SimpleInjector注册它(不是真的必要,因为它们是具体的类型,因此可以由容器在运行中创建),然后我使用当前的部分关闭我的ProfileWrapper类的实例配置文件作为通用参数,然后最后我将我的封闭实例注册为Singleton。 通过这种方式,您可以创建新的配置文件,而无需手动注册新的Wrappers。

就是这样。 现在,您不必依赖和注入IMapper,而是为您的ProfileWrapper注入您想要使用的Profile,如下所示:

 ProfileMapper appProfileMapper; ProfileMapper mvcProfileMapper; ProfileMapper guestProfile; 

等等。 每个Wrapper都是使用不同的MapperConfiguration使用不同的配置文件创建的。 由于包装器实现了IMapper,因此所有映射代码都保持不变。 不需要重构方法调用,只需要依赖类型。

如果您创建BaseProfile,只需更改ProfileMapper中的generics参数以仅接受此BaseProfile的实例。

Interesting Posts