How to register AutoMapper 4.2.0 with Simple Injector

时间:2016-02-12 19:29:35

标签: c# automapper simple-injector

Updated to AutoMapper 4.2.0, and following the migration guide available here: https://github.com/AutoMapper/AutoMapper/wiki/Migrating-from-static-API/f4784dac61b91a0df130e252c91a0efd76ff51de#preserving-static-feel. Trying to translate code on that page for StructureMap to Simple Injector. Can someone show me what this code looks like in 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<MapperConfiguration>().Use(config);
        For<IMapper>().Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));
    }
}

Simple Injector

?

3 个答案:

答案 0 :(得分:13)

This would be the equivalent:

var totalQuestions = $('.questions').size();
var currentQuestion = 0;
$questions = $('.questions');
$questions.hide();
$($questions.get(currentQuestion)).fadeIn();
var nee = $('#next').click(function(){
  $($questions.get(currentQuestion)).fadeOut(function(){
    currentQuestion = currentQuestion + 1;
    if(currentQuestion == totalQuestions){
      alert('You have reached the end!');
    } else {
      $($questions.get(currentQuestion)).fadeIn();
    }
  });
});

   var msg = (function(){
    return function(){
        d3.event.stopPropagation();
        $("#div1").show();
    }
})();

var whole = d3.selectAll('.v1');
    var wholeCanvas = whole.append("svg").attr("width", 200).attr("height", 135);
wholeCanvas.append("circle").attr("cx", 50)
                            .attr("cy", 50)
                            .attr("r", 40)
                            .on("click", msg);

//want something like this
//var msg = (function(){
//      if(questions)[0]
//    return function(){
//        d3.event.stopPropagation();
//        $("#div1").show();
//    }
//          else if(questions)[1]
//      return function(){
//        d3.event.stopPropagation();
//        $("#div2").show();
//    }
// })();

答案 1 :(得分:3)

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

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<MapperConfiguration>(config);
        container.Register<IMapper>(() => config.CreateMapper(container.GetInstance));
    }
}

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

基本上,从StructureMap真正改变的唯一事情就是最后两行。

答案 2 :(得分:0)

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

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

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

ProfileMapper<ApplicationProfile> appProfileMapper;
ProfileMapper<MvcProfile> mvcProfileMapper;
ProfileMapper<GuestProfile> guestProfile;

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

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