我有一个AutoMapperConfiguration
静态类,用于设置AutoMapper映射:
static class AutoMapperConfiguration()
{
internal static void SetupMappings()
{
Mapper.CreateMap<long, Category>.ConvertUsing<IdToEntityConverter<Category>>();
}
}
其中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
在其构造函数中使用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
。
在构造函数中添加了[Inject]
属性,其中IRepository
。仍然获得NullReferenceException
。
想到Ninject可能无法拦截AutoMapperConfiguration.SetupMappings()
中的OnApplicationStarted()
调用,我将其移动到我知道正确注入的内容,我的控制器之一,就像这样:
public class RepositoryController : Controller
{
static RepositoryController()
{
AutoMapperConfiguration.SetupMappings();
}
}
仍然获得NullReferenceException
。
我的问题是,如何让Ninject将IRepository
注入IdToEntityConverter
?
答案 0 :(得分:11)
@ ozczecho的答案是现货,但是我发布了代码的Ninject版本,因为它有一个小小的警告让我们陷入了一段时间:
IKernel kernel = null; // Make sure your kernel is initialized here
Mapper.Initialize(map =>
{
map.ConstructServicesUsing(t => kernel.Get(t));
});
您不能只将kernel.Get
传递给map.ConstructServicesUsing
,因为除了Type之外,该方法还有params
参数。但由于params是可选的,你可以创建lambda表达式来生成一个匿名函数来获得你需要的东西。
答案 1 :(得分:8)
您必须授予AutoMapper访问DI容器的权限。我们使用StructureMap,但我想下面的内容应该适用于任何DI。
我们使用它(在我们的一个Bootstrapper任务中)......
private IContainer _container; //Structuremap container
Mapper.Initialize(map =>
{
map.ConstructServicesUsing(_container.GetInstance);
map.AddProfile<MyMapperProfile>();
}