如何将 AutoMapper 与 Ninject.Web.Mvc 结合使用?
设置
我有一个 AutoMapperConfiguration
静态类,用于设置 AutoMapper 映射:
static class AutoMapperConfiguration()
{
internal static void SetupMappings()
{
Mapper.CreateMap<long, Category>.ConvertUsing<IdToEntityConverter<Category>>();
}
}
其中 IdToEntityConverter
是一个自定义 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);
}
}
< code>IdToEntityConverter 在其构造函数中采用一个 IRepository
,以便通过访问数据库将 ID 转换回实际实体。请注意它没有默认构造函数。
在我的 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;
}
所以 OnApplicationCreated( )
将调用 AutoMapperConfiguration.SetupMappings()
来设置映射,而 CreateKernel()
将把 NHibRepository
的实例绑定到IRepository
接口。
问题
每当我运行此代码并尝试让 AutoMapper 将类别 ID 转换回类别实体时,我都会收到 AutoMapperMappingException
,指出 IdToEntityConverter
上不存在默认构造函数。
尝试
向
IdToEntityConverter
添加了默认构造函数。现在我收到一个NullReferenceException
,这表明注入不起作用。将私有
_repo
字段设为公共属性,并添加[Inject]
属性。仍然收到NullReferenceException
。在采用
IRepository
的构造函数中添加了[Inject]
属性。仍然收到NullReferenceException
。考虑到 Ninject 可能无法拦截
OnApplicationStarted()
中的AutoMapperConfiguration.SetupMappings()
调用,我将其移至我知道正确注入的位置,一个我的控制器,如下所示:公共类 RepositoryController :控制器 { 静态存储库控制器() { AutoMapperConfiguration.SetupMappings(); } }
仍然收到
NullReferenceException
。
问题
我的问题是,如何让 Ninject 将 IRepository
注入到 IdToEntityConverter
中?
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 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
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
@ozczecho 的答案很准确,但我发布了 Ninject 版本的代码,因为它有一个小警告让我们困惑了一段时间:
你不能只将
kernel.Get
传递给map.ConstructServicesUsing
因为该方法除了 Type 之外还有一个params
参数。但由于参数是可选的,您只需创建 lambda 表达式来生成匿名函数即可获得所需的内容。@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:
You can't just pass in
kernel.Get
tomap.ConstructServicesUsing
because that method has aparams
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.您必须授予 AutoMapper 访问 DI 容器的权限。我们使用 StructureMap,但我想下面的内容应该适用于任何 DI。
我们使用它(在我们的 Bootstrapper 任务之一中)...
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)...