注入依赖到一个自定义模型绑定,并使用InRequestScope使用Ninject [英] Inject a dependency into a custom model binder and using InRequestScope using Ninject

查看:104
本文介绍了注入依赖到一个自定义模型绑定,并使用InRequestScope使用Ninject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用NInject与NInject.Web.Mvc。

I'm using NInject with NInject.Web.Mvc.

首先,我创建了一个简单的测试项目中,我想 IPostRepository 的一个实例,在同一个控制器和一个自定义的模型绑定之间共享Web请求。在我真正的项目,我需要这个,因为我得到 IEntityChangeTracker 的问题,我有效有两个存储库访问同一对象图。所以,让我的测试项目简单,我只是想分享一个虚拟存储库。

To start with, I've created a simple test project in which I want an instance of IPostRepository to be shared between a controller and a custom model binder during the same web request. In my real project, I need this because I'm getting IEntityChangeTracker problems where I effectively have two repositories accessing the same object graph. So to keep my test project simple, I'm just trying to share a dummy repository.

我遇到的问题是,它的工作原理上的第一个要求,就是这样。有关code如下。

The problem I'm having is that it works on the first request and that's it. The relevant code is below.

NInjectModule:

NInjectModule:

public class PostRepositoryModule : NinjectModule
{
    public override void Load()
    {
        this.Bind<IPostRepository>().To<PostRepository>().InRequestScope();
    }
}

CustomModelBinder:

CustomModelBinder:

public class CustomModelBinder : DefaultModelBinder
{
    [Inject]
    public IPostRepository repository { get; set; }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        repository.Add("Model binder...");

        return base.BindModel(controllerContext, bindingContext);
    }
}

public class HomeController : Controller
{
    private IPostRepository repository;

    public HomeController(IPostRepository repository)
    {
        this.repository = repository;
    }

    public ActionResult Index(string whatever)
    {
        repository.Add("Action...");

        return View(repository.GetList());
    }
}

Global.asax中:

Global.asax:

protected override void OnApplicationStarted()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    ModelBinders.Binders.Add(typeof(string), kernel.Get<CustomModelBinder>());
}

这样做,这样实际上是创建 IPostRepository 2个独立的实例,而不是共享的实例。这里有一些我的问候缺少注入到依赖我的模型粘合剂。我的code以上基于的 NInject.Web.Mvc维基但我用尽全力。

Doing it this way is actually creating 2 separate instances of IPostRepository rather than the shared instance. There's something here that I'm missing with regards to injecting a dependency into my model binder. My code above is based on the first setup method described in the NInject.Web.Mvc wiki but I have tried both.

当我没有使用第二种方法, IPostRepository 将只对第一个Web请求后,它会默认为不共享实例共享。然而,当我没有得到的工作,我用的是默认的 DependencyResolver ,因为我不能为我的生活弄清楚如何做同样的NInject(即如内核在NInjectMVC3类局促)。我这样做,像这样:

When I did use the second method, IPostRepository would be shared only for the very first web request, after which it would default to not sharing the instance. However, when I did get that working, I was using the default DependencyResolver as I couldn't for the life of me figure out how to do the same with NInject (being as the kernel is tucked away in the NInjectMVC3 class). I did that like so:

ModelBinders.Binders.Add(typeof(string),
    DependencyResolver.Current.GetService<CustomModelBinder>());

我怀疑这工作第一次的原因不仅是因为这不是通过NInject解决它,所以生命周期真的被MVC直接处理(虽然这意味着我不知道它是如何解决的依赖)。

I suspect the reason this worked the first time only is because this isn't resolving it via NInject, so the lifecycle is really being handled by MVC directly (although that means I have no idea how it's resolving the dependency).

因此​​,我怎么去正确注册我的模型绑定并获得NInject注入依赖?

So how do I go about properly registering my model binder and getting NInject to inject the dependency?

推荐答案

我最终设法与工厂来解决它的建议。但是,我只是无法弄清楚如何使用 Ninject.Extensions.Factory 做到这一点这是我会一直preferred。以下是我结束了:

I eventually managed to solve it with a factory as suggested. However, I just could not figure out how to accomplish this with Ninject.Extensions.Factory which is what I would've preferred. Here is what I ended up with:

该工厂接口:

public interface IPostRepositoryFactory
{
    IPostRepository CreatePostRepository();
}

工厂实现:

public class PostRepositoryFactory : IPostRepositoryFactory
{
    private readonly string key = "PostRepository";

    public IPostRepository CreatePostRepository()
    {
        IPostRepository repository;

        if (HttpContext.Current.Items[key] == null)
        {
            repository = new PostRepository();
            HttpContext.Current.Items.Add(key, repository);
        }
        else
        {
            repository = HttpContext.Current.Items[key] as PostRepository;
        }

        return repository;
    }
}

该Ninject模块厂:

The Ninject module for the factory:

public class PostRepositoryFactoryModule : NinjectModule
{
    public override void Load()
    {
        this.Bind<IPostRepositoryFactory>().To<PostRepositoryFactory>();
    }
}

在自定义模型粘合剂:

The custom model binder:

public class CustomModelBinder : DefaultModelBinder
{
    private IPostRepositoryFactory factory;

    public CustomModelBinder(IPostRepositoryFactory factory)
    {
        this.factory = factory;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        IPostRepository repository = factory.CreatePostRepository();

        repository.Add("Model binder");

        return base.BindModel(controllerContext, bindingContext);
    }
}

控制器:

public class HomeController : Controller
{
    private IPostRepository repository;

    public HomeController(IPostRepositoryFactory factory)
    {
        this.repository = factory.CreatePostRepository();
    }

    public ActionResult Index(string whatever)
    {
        repository.Add("Action method");

        return View(repository.GetList());
    }
}

Global.asax中要连接的自定义模型粘合剂:

Global.asax to wire up the custom model binder:

protected override void OnApplicationStarted()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    ModelBinders.Binders.Add(typeof(string), kernel.Get<CustomModelBinder>());
}

在我看来,给了我所需要的输出:

Which in my view, gave me the desired output of:

模型绑定结果
Action方法

这篇关于注入依赖到一个自定义模型绑定,并使用InRequestScope使用Ninject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆