如何使用Ninject将接口绑定到automapper

时间:2014-06-24 17:54:57

标签: ninject automapper

每当我调用automapper时我想使用DI,以便我可以解开一些我的图层。而不是像这样调用automapper:

 public class MyController : Controller 
 {

     public ActionResult MyAction(MyModel model)
     {
          var newModel= Mapper.Map<MyModel, NewModel>(model);
          return View(model);
      }
  }

我想这样做:

  public class MyController : Controller 
 {

     IMappingEngine _mappingEngine;

     public MyController(IMappingEngine mappingEngine)
     {   
        _mappingEngine = mappingEngine;
     }

     public ActionResult MyAction(MyModel model)
     {
          var newModel= _mappingEngine.Map<MyModel, NewModel>(model);
          return View(model);
      }
  }

我使用Ninject作为我的IOC。我如何将接口绑定到它?

我还需要提一下,我正在使用个人资料并且已经拥有:

var profileType = typeof(Profile);
        // Get an instance of each Profile in the executing assembly.
        var profiles = Assembly.GetExecutingAssembly().GetTypes()
            .Where(t => profileType.IsAssignableFrom(t)
                && t.GetConstructor(Type.EmptyTypes) != null)
            .Select(Activator.CreateInstance)
            .Cast<Profile>();

        // Initialize AutoMapper with each instance of the profiles found.
        Mapper.Initialize(a => profiles.ForEach(a.AddProfile));

我知道我缺少的步骤涉及与核心绑定:

kernel.Bind<IMappingEngine>.To<>(); //I do not know what
//to bind it to here so that when I call IMappingEngine;
//It will trigger my maps from my automapper profiles.

1 个答案:

答案 0 :(得分:2)

我似乎无法在AutoMapper存储库(https://github.com/AutoMapper/AutoMapper/search?q=IMappingService)中找到IMappingService。但是,有IMappingEngine

你所要做的就是

IBindingRoot.Bind<IMappingEngine>().ToMethod(x => Mapper.Engine);

IBindingRoot.Bind<IMappingEngine>().To<MappingEngine>();
IBindingRoot.Bind<IConfigurationProvider>().ToMethod(x => Mapper.Engine.ConfigurationProvider);

你很高兴。

但请注意,首次访问Mapper.EngineMapper.ConfigurationProvider会初始化AutoMapper。

因此,如果没有绑定,AutoMapper会在您第一次执行Mapper.Map<,>之类的操作时初始化。通过绑定,它将在第一次构造一个被注入IMappingEngine的对象时初始化。

如果要保留先前的初始化行为,可以选择以下几种方法:。

  • a)而不是注入IMappingEngine注入Lazy<IMappingEngine>(我认为这需要ninject.extensions.factory扩展)
  • b)将IMappingEngine绑定到代理(没有目标)。代理应仅在Mapper.Engine方法时访问.Intercept(...)。它也应该转发方法调用。
  • c)编写自己的LazyInitializedMappingEngine : IMappingEngine实现,除了将每个方法都转发到Mapper.Engine之外什么都不做。

我可能会选择c),其他人的工作太多了。 c)只要IMappingEngine的接口发生变化,就需要进行代码自适应。 b)不会但更复杂,更慢。 a)正在渗透到界面的所有消费者,偶尔会出错,破坏东西,有点难以追溯,所以我也不会这样做。


C):

public class LazyInitializedMappingEngine : IMappingEngine
{
    public IConfigurationProvider ConfigurationProvider { get { return Mapper.Engine.ConfigurationProvider; } }

    public TDestination Map<TDestination>(object source)
    {
        return Mapper.Map<TDestination>(source);
    }

    public TDestination Map<TDestination>(object source, Action<IMappingOperationOptions> opts)
    {
        return Mapper.Map<TDestination>(source, opts);
    }

    public TDestination Map<TSource, TDestination>(TSource source)
    {
        return Mapper.Map<TSource, TDestination>(source);
    }

    //... and so on ...
}

kernel.Bind<IMappingEngine>().To<LazyInitializedMappingEngine>();