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开发者_StackOverflow社区 _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 aNullReferenceException
, 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 gettingNullReferenceException
.Added the
[Inject]
attribute on the constructor that takes anIRepository
. Still gettingNullReferenceException
.Thinking that perhaps Ninject can't intercept the
AutoMapperConfiguration.SetupMappings()
call inOnApplicationStarted()
, 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
?
@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.
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>();
}
精彩评论