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.
