我正在使用NInject与NInject.Web.Mvc.
首先,我创建了一个简单的测试项目,我希望在同一个Web请求期间在控制器和自定义模型绑定器之间共享一个IPostRepository实例.在我的真实项目中,我需要这个,因为我遇到了IEntityChangeTracker问题,我实际上有两个存储库访问同一个对象图.因此,为了保持我的测试项目简单,我只是想共享一个虚拟存储库.
我遇到的问题是它适用于第一个请求,就是这样.相关代码如下.
NInjectModule:
public class PostRepositoryModule : NinjectModule { public override void Load() { this.Bind<IPostRepository>().To<PostRepository>().InRequestScope(); } }
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中:
protected override void OnApplicationStarted() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.Add(typeof(string),kernel.Get<CustomModelBinder>()); }
这样做实际上是创建2个独立的IPostRepository实例而不是共享实例.这里有一些关于将依赖项注入模型绑定器的问题.我上面的代码是基于NInject.Web.Mvc wiki中描述的第一种设置方法,但我已经尝试了两种方法.
当我使用第二种方法时,IPostRepository仅为第一个Web请求共享,之后它将默认不共享实例.然而,当我确实工作时,我正在使用默认的DependencyResolver,因为在我的生活中我无法弄清楚如何对NInject做同样的事情(因为内核隐藏在NInjectMVC3类中).我是这样做的:
ModelBinders.Binders.Add(typeof(string),DependencyResolver.Current.GetService<CustomModelBinder>());
我怀疑它第一次运行的原因仅仅是因为它没有通过NInject解析它,所以生命周期实际上是由MVC直接处理的(虽然这意味着我不知道它如何解决依赖关系).
那么我该如何正确注册我的模型绑定器并让NInject注入依赖?
解决方法
ModelBinder由MVC重用于多个请求.这意味着它们的生命周期比请求范围更长,因此不允许依赖具有较短请求范围生命周期的对象.
使用Factory代替为每次执行BindModel创建IPostRepository