[英]How to register AutoMapper 4.2.0 with Simple Injector
更新到 AutoMapper 4.2.0,并遵循此处提供的迁移指南: https : //github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API/f4784dac61b91a0df130e252c91a0efd76ff51de#preserving-static-feel 。 尝试将该页面上的 StructureMap 代码转换为 Simple Injector。 有人可以告诉我这段代码在 Simple Injector 中的样子吗?
结构图
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<MapperConfiguration>().Use(config);
For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));
}
}
简单的注射器
?
这将是等价的:
container.RegisterInstance<MapperConfiguration>(config);
container.Register<IMapper>(() => 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.RegisterInstance<MapperConfiguration>(config);
container.Register<IMapper>(() => config.CreateMapper(container.GetInstance));
}
}
您需要添加SimpleInjector.Packaging包,然后添加对container.RegisterPackages();
的调用container.RegisterPackages();
在您的引导程序/配置代码中。
本质上,StructureMap 唯一真正改变的是最后两行。
为了将多个 IMapper 映射到不同的 MapperConfiguration 对象,这似乎是一个反复出现的问题,我推荐以下方法,它甚至不需要重构映射器方法调用:
1)围绕 IMapper 接口创建一个通用包装器。 这个包装器可以是接口或类,但显然最终你必须实现你的包装器,所以我将在下面展示具体的类。 让这个包装器实现(或继承,如果您选择制作接口)IMapper 接口,如下所示:
public class ProfileMapper<TProfile> : 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();
}
}
通用参数必须是“配置文件”的子类,因为从该配置文件中您将获得映射器配置。
2) 在该类中,只需将调用重定向到您在构造函数中创建的私有 IMapper 实例,即可实现 IMapper 接口,如下所示:
public TDestination Map<TDestination>(object source)
{
return mapper.Map<TDestination>( source );
}
3) 现在您需要在 Simple Injector 中为您拥有的每个 Profile 注册这个 ProfileMapper 类的一个部分关闭的实例。 您首先通过获取从 Profile 继承的所有类来完成此操作,然后创建这个部分关闭的实例,然后注册它。 有多种方法可以获取所有 Profile 类,但我采用了以下方法:
IEnumerable<Type> 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 继承的所有类型,位于所述命名空间中。 然后对于每个配置文件,我用 SimpleInjector 注册它(不是真的有必要,因为它们是具体的类型,因此可以由容器动态创建),然后我使用当前的 ProfileWrapper 类创建一个部分关闭的实例Profile 作为通用参数,最后我将关闭的实例注册为单例。 通过这种方式,您可以创建新的配置文件,而无需手动注册新的包装器。
就是这样。 现在,您不再依赖并注入 IMapper,而是将您要使用的 Profile 注入到 ProfileWrapper 中,如下所示:
ProfileMapper<ApplicationProfile> appProfileMapper;
ProfileMapper<MvcProfile> mvcProfileMapper;
ProfileMapper<GuestProfile> guestProfile;
等等。 每个 Wrapper 都是使用不同的配置文件使用单独的 MapperConfiguration 创建的。 由于包装器实现了 IMapper,您的所有映射代码都保持不变。 不需要重构方法调用,只需要重构依赖类型。
如果您创建一个 BaseProfile,只需更改 ProfileMapper 中的通用参数以仅接受此 BaseProfile 的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.