如何在Ninject.Web.Mvc中使用AutoMapper?

时间:2010-11-02 02:54:32

标签: c# dependency-injection inversion-of-control ninject automapper

设置

我有一个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上没有默认构造函数。

尝试

  1. IdToEntityConverter添加了默认构造函数。现在我得到NullReferenceException,这表明注射不起作用。

  2. 将私有_repo字段设置为公共属性,并添加了[Inject]属性。仍然获得NullReferenceException

  3. 在构造函数中添加了[Inject]属性,其中IRepository。仍然获得NullReferenceException

  4. 想到Ninject可能无法拦截AutoMapperConfiguration.SetupMappings()中的OnApplicationStarted()调用,我将其移动到我知道正确注入的内容,我的控制器之一,就像这样:

    public class RepositoryController : Controller
    {
        static RepositoryController()
        {
            AutoMapperConfiguration.SetupMappings();
        }
    }
    

    仍然获得NullReferenceException

  5. 问题

    我的问题是,如何让Ninject将IRepository注入IdToEntityConverter

2 个答案:

答案 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>();
    }