关于使用Ninject的问题 [英] Questions about using Ninject

查看:97
本文介绍了关于使用Ninject的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经过了推荐的步骤,将Ninject添加到我的MVC应用程序。并且我向控制器的构造函数添加了一个 DbContext 参数。

I went through the recommended steps to add Ninject to my MVC application. And I added a DbContext argument to my controllers' constructors.

控制器: / p>

Controller:

public class MyController : BaseController
{
    public ArticlesController(MyDbContext context)
        : base(context)
    { }
}

基本控制器: strong>

Base Controller:

public class BaseController : Controller
{
    protected DbContext MyDbContext;

    public BaseController(MyDbContext context)
    {
        MyDbContext = context;
    }
}

这似乎很好。但是请留下几个问题。

This seems to work well. But leaves me with a few questions.


  1. Ninject确保我的 DbContext 被清理并及时处理

我已经为所有应用程序的控制器创建了一个基类来处理任何常见的初始化等。类在构造函数中接受我的 DbContext 参数的一个实例。但这需要我也添加这个参数到我的应用程序中的每个控制器。有没有办法不要求这个?

I have created a base class for all my application's controllers to handle any common initialization, etc. The base class accepts an instance of my DbContext argument in the constructor. But this requires me to also add this argument to every controller in my app. Is there any way to not require this?

我不知道创建一个我的 DbContext 。有没有办法进行优化,只有当请求实际上要求我访问数据库时,才能创建它。

I'm not sure how expensive it is to create an instance of my DbContext. Is there any way to make the optimization that it only gets created if the request actually requires me to access the database.


推荐答案


Ninject是否确保我的DbContext被及时清理和处理?

Does Ninject ensure my DbContext is cleaned up and disposed in a timely fashion?

根据此答案


CLR文档指出,创建Disposable对象的任何人都负责调用Dispose。在这种情况下,对象是由Ninject创建的。这意味着你不应该明确地调用Dispose。

The CLR documentation states that whoever creates a Disposable object is responsible for calling Dispose. In this case the object is created by Ninject. That means you should not call Dispose explicitly.

Ninject将每个Disposable对象放在另一范围以外的 InTransientScope a href =https://web.archive.org/web/20130111064153/http://kohari.org/2009/03/06/cache-and-collect-lifecycle-management-in-ninject-20/ =nofollow>只要所创建的对象被绑定的范围对象由GC收集。这就是为什么每个Disposable对象应该是Bindd,范围不是InTransientScope()。例如。您可以使用 NamedScope扩展程序中的InParentScope(),这将尽快处理该对象作为被注入的对象是垃圾回收。

Ninject disposes every Disposable object that has another scope other than InTransientScope as soon as the scope object to which the created object is tied is collected by GC. That's why every Disposable object should be Bindd with a scope that is not InTransientScope(). E.g. you can use InParentScope() from the NamedScope extension which will Dispose the object as soon as the object it is injected into is garbage collected.








我为所有应用程序的控制器创建了一个基类来处理任何常见的初始化等。基类接受构造函数中DbContext参数的一个实例。但这需要我也添加这个参数到我的应用程序中的每个控制器。有没有办法不要求这个?

I have created a base class for all my application's controllers to handle any common initialization, etc. The base class accepts an instance of my DbContext argument in the constructor. But this requires me to also add this argument to every controller in my app. Is there any way to not require this?

简单地说, 永不使用MVC控制器的常用基类。类继承往往紧紧耦合你的逻辑,随着时间的推移变得难以维持。它也会导致您创建一个 god对象,因为创建多级注入的依赖关系将意味着每个控制器都需要更多的依赖关系。

Simply put, never use a common base class for MVC Controllers. Class inheritance tends to tightly couple your logic and it becomes difficult to maintain over time. It also tends to lead you to create a god object, because creating multiple levels of injected dependencies would mean even more required dependencies for every Controller.

如果您有交叉关切,您应该使用全局注册过滤器。您可以为每个逻辑单独制作一个过滤器,而不会像共享基类那样违反单一责任原则。如果您在全局注册过滤器,可以使用构造函数注入,如此操作过滤器此授权过滤器。您还可以自己创建属性(无行为)使其成为

If you have cross-cutting concerns, you should use globally registered filters instead. You can make a separate filter for each piece of logic, which doesn't violate the Single Responsibility Principle as a shared base class would. And if you register your filters globally, you can use constructor injection as in this action filter or this authorization filter. You can also make your own attributes (without behavior) to make them conditional per controller and/or action, if necessary.

既然你明确地说你想要根据当前用户设置常见的 ViewBag 属性,这里是如何使用过滤器完成的。

Since you explicitly said you wanted to set common ViewBag properties based on the current user, here is how that can be done with filters.

public class CurrentUserProfileFilter : IAuthorizationFilter
{
    private readonly MyDbContext context;

    public CurrentUserAuthorizationFilter(MyDbContext context)
    {
        this.context = context;
    }

    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var currentUserName = filterContext.HttpContext.User.Identity.Name;

        // Set the ViewBag for the request.
        filterContext.Controller.ViewBag.UserName = currentUserName;

        var userBirthdate = 
            from user as this.context.AspNetUsers
            where user.UserName == currentUserName
            select birthdate;

        if (userBirthdate.Date == DateTime.Now.Date)
        {
            filterContext.Controller.ViewBag.Message = "Happy Birthday!";
        }
    }
}



GlobalFilterProvider



MVC有一个静态的 GlobalFiltersCollection 你应该在全局注册过滤器实例。对于具有由DI容器管理的生命周期的依赖关系的过滤器(例如 DbContext )而言,这并不适用。

GlobalFilterProvider

MVC has a static GlobalFiltersCollection where you are supposed to register filter instances globally. This isn't going to do for filters that have dependencies that have lifetimes that are managed by the DI container (such as DbContext).

为了确保过滤器按需解析(每个请求),我们制作一个 IFilterProvider ,通过容器解析它们(假设您的Ninject容器已注册使用MVC作为DependencyResolver);

To ensure the filters are resolved on demand (per-request), we make an IFilterProvider that resolves them through the container (assuming your Ninject container is registered with MVC as the DependencyResolver);

public class GlobalFilterProvider : IFilterProvider
{
    private readonly IDependencyResolver dependencyResolver;

    public GlobalFilterProvider(IDependencyResolver dependencyResolver)
    {
        this.dependencyResolver = dependencyResolver;
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        foreach (var filter in this.dependencyResolver.GetServices<IActionFilter>())
        {
            yield return new Filter(filter, FilterScope.Global, order: null);
        }
        foreach (var filter in this.dependencyResolver.GetServices<IAuthorizationFilter>())
        {
            yield return new Filter(filter, FilterScope.Global, order: null);
        }
        foreach (var filter in this.dependencyResolver.GetServices<IExceptionFilter>())
        {
            yield return new Filter(filter, FilterScope.Global, order: null);
        }
        foreach (var filter in this.dependencyResolver.GetServices<IResultFilter>())
        {
            yield return new Filter(filter, FilterScope.Global, order: null);
        }
        // If MVC 5, add these as well...
        //foreach (var filter in this.dependencyResolver.GetServices<System.Web.Mvc.Filters.IAuthenticationFilter>())
        //{
        //    yield return new Filter(filter, FilterScope.Global, order: null);
        //}
    }
}



用法



在您的Ninject组合根中,使用内核注册过滤器的实例,以实现其实现的过滤器接口的类型或类型

Usage

In your Ninject composition root, register the instance of your filter with the kernel for the type or types of filter interfaces it implements.

// Self-bind our filter, so dependencies can be injected.
kernel.Bind<IAuthorizationFilter>().To<CurrentUserProfileFilter>();

FilterConfig 中注册过滤器提供程序。

In FilterConfig, register your filter provider.

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());

        // Register the filter provider with MVC.
        FilterProviders.Providers.Insert(0, new GlobalFilterProvider(DependencyResolver.Current));
    }
}

现在,在每个请求中,填充您的用户详细信息。

Now on every request, your user details are populated.

但更重要的是,您的 ArticlesController 不需要 MyDbContext 作为依赖关系,也没有其他控制器。

But more importantly, your ArticlesController doesn't require MyDbContext as a dependency, nor do the rest of your controllers.


我不知道创建一个我的DbContext。有没有办法进行优化,只有当请求实际上要求我访问数据库时才会创建它。

I'm not sure how expensive it is to create an instance of my DbContext. Is there any way to make the optimization that it only gets created if the request actually requires me to access the database.

看看在这个问题:每个Web请求一个DbContext ...为什么?

这篇关于关于使用Ninject的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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