[英]How do I use AutoMapper with Ninject.Web.Mvc?
I have an AutoMapperConfiguration
static class that sets up the AutoMapper mappings: 我有一个AutoMapperConfiguration
静态类,用于设置AutoMapper映射:
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: 其中IdToEntityConverter<T>
是一个自定义的ITypeConverter
,如下所示:
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. IdToEntityConverter
在其构造函数中获取IRepository
,以便通过命中数据库将ID转换回实际实体。 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()
: 在我的ASP.NET的Global.asax
,这就是我对OnApplicationStarted()
和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. 因此OnApplicationCreated()
将调用AutoMapperConfiguration.SetupMappings()
来设置映射, CreateKernel()
将NHibRepository
的实例绑定到IRepository
接口。
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
. 每当我运行此代码并尝试让AutoMapper将类别ID转换回类别实体时,我会得到一个AutoMapperMappingException
,它表示IdToEntityConverter
上不存在默认构造IdToEntityConverter
。
Added a default constructor to IdToEntityConverter
. 为IdToEntityConverter
添加了默认构造IdToEntityConverter
。 Now I get a NullReferenceException
, which indicates to me that the injection isn't working. 现在我得到一个NullReferenceException
,它向我表明注入不起作用。
Made the private _repo
field into a public property and added the [Inject]
attribute. 将private _repo
字段设置为公共属性并添加[Inject]
属性。 Still getting NullReferenceException
. 仍然得到NullReferenceException
。
Added the [Inject]
attribute on the constructor that takes an IRepository
. 在带有IRepository
的构造函数上添加了[Inject]
属性。 Still getting NullReferenceException
. 仍然得到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: 想想Ninject可能无法拦截OnApplicationStarted()
的AutoMapperConfiguration.SetupMappings()
调用,我把它移动到我知道注入正确的东西,我的一个控制器,如下所示:
public class RepositoryController : Controller { static RepositoryController() { AutoMapperConfiguration.SetupMappings(); } }
Still getting NullReferenceException
. 仍然得到NullReferenceException
。
My question is, how do I get Ninject to inject an IRepository
into IdToEntityConverter
? 我的问题是,如何让Ninject将一个IRepository
注入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: @ ozczecho的回答是现实的,但是我发布了Ninject版本的代码,因为它有一个小小的警告,抓住了我们一段时间:
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. 你不能只将kernel.Get
传递给map.ConstructServicesUsing
因为除了Type之外,该方法还有一个params
参数。 But since params are optional, you can just create the lambda expression to generate an anonymous function to get you what you need. 但是因为params是可选的,所以你可以创建lambda表达式来生成一个匿名函数来获得你需要的东西。
You have to give AutoMapper access to the DI container. 您必须授予AutoMapper访问DI容器的权限。 We use StructureMap, but I guess the below should work with any DI. 我们使用StructureMap,但我想下面的内容应该适用于任何DI。
We use this (in one of our Bootstrapper tasks)... 我们使用它(在我们的一个Bootstrapper任务中)......
private IContainer _container; //Structuremap container
Mapper.Initialize(map =>
{
map.ConstructServicesUsing(_container.GetInstance);
map.AddProfile<MyMapperProfile>();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.