注入依赖到一个自定义模型绑定,并使用InRequestScope使用Ninject [英] Inject a dependency into a custom model binder and using InRequestScope using 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屋!