问题描述
我按照推荐的步骤将 Ninject 添加到我的 MVC 应用程序中.我在控制器的构造函数中添加了一个 DbContext
参数.
控制器:
公共类 MyController : BaseController{公共 ArticlesController(MyDbContext 上下文):基础(上下文){ }}
基本控制器:
公共类 BaseController : 控制器{受保护的 DbContext MyDbContext;公共 BaseController(MyDbContext 上下文){MyDbContext = 上下文;}}
这似乎运作良好.但是给我留下了几个问题.
Ninject 是否确保我的
DbContext
被及时清理和处置?我为所有应用程序的控制器创建了一个基类,以处理任何常见的初始化等.基类在构造函数中接受我的
DbContext
参数的实例.但这要求我还要将此参数添加到我的应用程序中的每个控制器.有什么办法不需要这个?我不确定创建我的
DbContext
实例的成本有多大.有没有什么办法可以优化它只在请求实际上需要我访问数据库时才创建.
Ninject 是否确保及时清理和处置我的 DbContext?
根据这个答案:
<块引用>CLR 文档指出,创建 Disposable 对象的人负责调用 Dispose.在这种情况下,对象是由 Ninject 创建的.这意味着您不应显式调用 Dispose.
Ninject 会处理除
InTransientScope
一旦创建对象所绑定的范围对象被 GC 收集.这就是为什么每个 Disposable 对象都应该与不是 InTransientScope() 的范围绑定的原因.例如.您可以使用 NamedScope 扩展 中的 InParentScope() 将对象作为一旦它被注入的对象被垃圾回收.
<块引用>我为所有应用程序的控制器创建了一个基类,以处理任何常见的初始化等.基类在构造函数中接受我的 DbContext 参数的实例.但这要求我还要将此参数添加到我的应用程序中的每个控制器.有什么办法不需要这个?
简单地说,从不为 MVC 控制器使用公共基类.类继承往往会紧密耦合您的逻辑,并且随着时间的推移变得难以维护.它还倾向于引导您创建一个 god 对象,因为创建多个级别的注入依赖项会意味着每个 Controller 需要更多的依赖项.
如果您有横切关注点,您应该使用全局注册的过滤器.您可以为每条逻辑制作单独的过滤器,这不会像共享基类那样违反单一责任原则.如果您在全局范围内注册过滤器,则可以使用构造函数注入,如 此操作过滤器或这个授权过滤器.您也可以制作自己的属性(无行为)如有必要,它们是每个控制器和/或操作的条件.
示例:
由于您明确表示要根据当前用户设置通用 ViewBag
属性,因此可以使用过滤器来完成此操作.
当前用户配置文件过滤器
公共类 CurrentUserProfileFilter : IAuthorizationFilter{私有只读 MyDbContext 上下文;公共 CurrentUserAuthorizationFilter(MyDbContext 上下文){this.context = 上下文;}公共无效 OnAuthorization(AuthorizationContext filterContext){var currentUserName = filterContext.HttpContext.User.Identity.Name;//为请求设置 ViewBag.filterContext.Controller.ViewBag.UserName = 当前用户名;var userBirthdate =从用户作为 this.context.AspNetUsers其中 user.UserName == currentUserName选择生日;if (userBirthdate.Date == DateTime.Now.Date){filterContext.Controller.ViewBag.Message = 生日快乐!";}}}
GlobalFilterProvider
MVC 有一个静态的 GlobalFiltersCollection
,您应该在其中全局注册过滤器实例.这不适用于具有由 DI 容器管理的生命周期的依赖项的过滤器(例如 DbContext
).
为确保过滤器按需解析(按请求),我们制作了一个 IFilterProvider
,通过容器解析它们(假设您的 Ninject 容器已向 MVC 注册为 DependencyResolver);
公共类 GlobalFilterProvider : IFilterProvider{私有只读 IDependencyResolver 依赖解析器;公共 GlobalFilterProvider(IDependencyResolver dependencyResolver){this.dependencyResolver = 依赖解析器;}公共 IEnumerable<过滤器>GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor){foreach(this.dependencyResolver.GetServices() 中的 var 过滤器){yield return new Filter(filter, FilterScope.Global, order: null);}foreach(this.dependencyResolver.GetServices() 中的 var 过滤器){yield return new Filter(filter, FilterScope.Global, order: null);}foreach(this.dependencyResolver.GetServices() 中的 var 过滤器){yield return new Filter(filter, FilterScope.Global, order: null);}foreach(this.dependencyResolver.GetServices() 中的 var 过滤器){yield return new Filter(filter, FilterScope.Global, order: null);}//如果 MVC 5,也添加这些...//foreach (var filter in this.dependencyResolver.GetServices())//{//yield return new Filter(filter, FilterScope.Global, order: null);/