Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

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

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

  4. 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?

like image 659
Daniel T. Avatar asked Nov 02 '10 02:11

Daniel T.


1 Answers

@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.

like image 106
Charles Boyung Avatar answered Sep 21 '22 00:09

Charles Boyung