繁体   English   中英

如何使用 Simple Injector 注册 AutoMapper 4.2.0

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM