How do I use AutoMapper with Ninject.Web.Mvc?

Setup

I have an AutoMapperConfiguration static class that sets up the AutoMapper mappings:

static class AutoMapperConfiguration()
{
    internal static void SetupMappings()
    {
        Mapper.CreateMap<long, Category>.ConvertUsing<IdToEntityConverter<Category>>();
    }
}

where IdToEntityConverter<T> is a custom ITypeConverter that looks like this:

class IdToEntityConverter<T> : ITypeConverter<long, T> where T : Entity
{
    private readonly IRepository _repo;

    public IdToEntityConverter(IRepository repo)
    {
        _repo = repo;
    }

    public T Convert(ResolutionContext context)
    {
        return _repo.GetSingle<T>(context.SourceValue);
    }
}

IdToEntityConverter takes an IRepository in its constructor in order to convert an ID back to the actual entity by hitting up the database. Notice how it doesn't have a default constructor.

In my ASP.NET's Global.asax , this is what I have for OnApplicationStarted() and CreateKernel() :

protected override void OnApplicationStarted()
{
    // stuff that's required by MVC
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);

    // our setup stuff
    AutoMapperConfiguration.SetupMappings();
}

protected override IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<IRepository>().To<NHibRepository>();

    return kernel;
}

So OnApplicationCreated() will call AutoMapperConfiguration.SetupMappings() to set up the mappings and CreateKernel() will bind an instance of NHibRepository to the IRepository interface.

Problem

Whenever I run this code and try to get AutoMapper to convert a category ID back to a category entity, I get an AutoMapperMappingException that says no default constructor exists on IdToEntityConverter .

Attempts

  • Added a default constructor to IdToEntityConverter . Now I get a NullReferenceException , which indicates to me that the injection isn't working.

  • Made the private _repo field into a public property and added the [Inject] attribute. Still getting NullReferenceException .

  • Added the [Inject] attribute on the constructor that takes an IRepository . Still getting NullReferenceException .

  • Thinking that perhaps Ninject can't intercept the AutoMapperConfiguration.SetupMappings() call in OnApplicationStarted() , I moved it to something that I know is injecting correctly, one of my controllers, like so:

    public class RepositoryController : Controller
    {
        static RepositoryController()
        {
            AutoMapperConfiguration.SetupMappings();
        }
    }
    

    Still getting NullReferenceException .

  • Question

    My question is, how do I get Ninject to inject an IRepository into IdToEntityConverter ?


    You have to give AutoMapper access to the DI container. We use StructureMap, but I guess the below should work with any DI.

    We use this (in one of our Bootstrapper tasks)...

        private IContainer _container; //Structuremap container
    
        Mapper.Initialize(map =>
        {
            map.ConstructServicesUsing(_container.GetInstance);
            map.AddProfile<MyMapperProfile>();
        }
    

    @ozczecho's answer is spot-on, but I'm posting the Ninject version of the code because it has one little caveat that caught us for a while:

    IKernel kernel = null; // Make sure your kernel is initialized here
    
    Mapper.Initialize(map =>
    {
        map.ConstructServicesUsing(t => kernel.Get(t));
    });
    

    You can't just pass in kernel.Get to map.ConstructServicesUsing because that method has a params parameter in addition to the Type. But since params are optional, you can just create the lambda expression to generate an anonymous function to get you what you need.

    链接地址: http://www.djcxy.com/p/74394.html

    上一篇: 我应该在单元测试中使用AutoMapper吗?

    下一篇: 如何在Ninject.Web.Mvc中使用AutoMapper?