如何将 AutoMapper 与 Ninject.Web.Mvc 结合使用?

发布于 2024-09-29 20:23:40 字数 2599 浏览 4 评论 0原文

设置

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

尝试

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

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

  3. 在采用 IRepository 的构造函数中添加了 [Inject] 属性。仍然收到 NullReferenceException

  4. 考虑到 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

  1. Added a default constructor to IdToEntityConverter. Now I get a NullReferenceException, which indicates to me that the injection isn't working.

  2. Made the private _repo field into a public property and added the [Inject] attribute. Still getting NullReferenceException.

  3. Added the [Inject] attribute on the constructor that takes an IRepository. Still getting NullReferenceException.

  4. 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:

    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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅暮の光 2024-10-06 20:23:40

@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 参数。但由于参数是可选的,您只需创建 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:

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.

指尖上的星空 2024-10-06 20:23:40

您必须授予 AutoMapper 访问 DI 容器的权限。我们使用 StructureMap,但我想下面的内容应该适用于任何 DI。

我们使用它(在我们的 Bootstrapper 任务之一中)...

    private IContainer _container; //Structuremap container

    Mapper.Initialize(map =>
    {
        map.ConstructServicesUsing(_container.GetInstance);
        map.AddProfile<MyMapperProfile>();
    }

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>();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文