c# – 如何访问Ninject.Kernel而不使用Service Locator模式

前端之家收集整理的这篇文章主要介绍了c# – 如何访问Ninject.Kernel而不使用Service Locator模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经阅读了关于这个主题的几十个帖子,没有找到一个明确的准则,如何访问Ninject.Kernel而不使用服务定位器模式.

我目前在需要使用CustomerBusiness(这是我的服务)的课程中有以下这些,它的工作正常,但我很清楚,这不是推荐的方法.

private CustomerBusiness _customerBusiness;

private ICustomerRepository CustomerRepository
{
    get { return NinjectWebCommon.Kernel.Get<IAccountRepository>(); }
}

private CustomerBusiness CustomerBusiness
{
    get
    {
        if (_customerBusiness == null)
        {
            _customerBusiness = new CustomerBusiness(AccountRepository);
        }

        return _customerBusiness;
    }
}

public Customer GetCustomer(int id)
{
    return CustomerBusiness.GetCustomer(id);
}

这是在上面的代码中访问的内核属性

public static IKernel Kernel
{
    get
    {
        return CreateKernel();
    }
}

我已经阅读了许多有关使用工厂的建议,但是他们都没有解释如何使用这个工厂.我真的很感激任何人可以向我显示“CustomerFactory”或任何其他建议的方法,包括如何使用它.

更新

我正在使用ASP.NET Web窗体,需要从CodeBehind访问CustomerBusiness.

我发现这个工作的最终解决方案是这个帖子中最多的答案:
How can I implement Ninject or DI on asp.net Web Forms?

它看起来像这样(来自PageBase的继承,它是Ninject.Web的一部分 – 这是关键!):

public partial class Edit : PageBase
{
    [Inject]
    public ICustomerBusiness CustomerBusiness { get; set; }
    ...

下面接受的答案间接导致我找到这个解决方案.

解决方法

因为你使用NinjectWebCommon,我假设你有一个Web应用程序.你真的只能在一个地方访问Ninject内核 – 在 composition root.这是你建立对象图的地方,唯一应该需要访问IoC容器的地方.要实际获得您需要的依赖项,您通常使用 constructor injection.

例如,在MVC Web应用程序的情况下,您有一个使用Ninject内核的控制器工厂,这是唯一引用它的地方.

为了扩展您的特定情况,您的课程将在其构造函数中接受ICustomerBusiness,声明它需要一个ICustomerBusiness实例作为其依赖关系:

class CustomerBusinessConsumer : ICustomerBusinessConsumer
{
    private readonly ICustomerBusiness customerBusiness;

    public CustomerBusinessConsumer(ICustomerBusiness customerBusiness)
    {
        this.customerBusiness = customerBusiness;
    }
    ...
}

现在,无论哪个类使用ICustomerBusinessConsumer作为其依赖关系,都将遵循相同的模式(接受ICustomerBusinessConsumer的实例作为其构造函数).您基本上从来没有使用新的(特定的例外)手动构建您的依赖关系.

然后,你只需要确保你的类获得它们的依赖关系,这个组合根是你做这个的.组合根究竟取决于您正在编写的应用程序的类型(控制台应用程序,WPF应用程序,Web服务,MVC Web应用程序…)

编辑:让我熟悉ASP.NET WebForms领域的情况
我从来没有使用过我的细节.不幸的是,WebForms要求您在每个Page类中都有一个无参数的构造函数,因此您无法从顶部的对象图形到底部使用构造函数注入.

然而,在咨询了Mark Seeman关于在WebForms中编写对象的章节之后,我可以重新说明如何处理该框架的低效率,同时仍然符合良好的DI实践:

>有一个负责解决依赖关系的类,使用你设置的Ninject的内核.这可能是内核周围非常薄的包装.让我们称它为DependencyContainer.
>创建容器并将其保存在应用程序上下文中,以便在需要时准备就绪

protected void Application_Start(object sender,EventArgs e)
{
   this.Application["container"] = new DependencyContainer();
}

>让我们假设你的页面类(让我们称之为HomePage)具有对ICustomerBusinessConsumer的依赖.然后DependencyContainer必须允许我们检索一个ICustomerBusinessConsumer的实例:

public ICustomerBusinessConsumer ResolveCustomerBusinessConsumer()
{
    return Kernel.Get<ICustomerBusinessConsumer>();
}

>在MainPage类本身中,您将在默认构造函数中解析其依赖关系:

public MainPage()
{
    var container = (DependencyContainer) HttpContext.Current.Application["container"];
    this.customerBusinessConsumer = container.ResolveCustomerBusinessConsumer();
}

几个注释:

>在HttpContext中具有可用的依赖项容器不能太诱人地将其视为服务定位器.实际上,这里最好的做法(至少从DI到DI的角度来看)就是要有一些“实现者”类,你将继承你的页面类的功能.

例如,MainPage处理的每个操作将只会转发给其实现者类.这个实现者类将是MainPage的依赖,并且与所有其他依赖关系一样,将使用容器来解析.

重要的部分是这些实现者类应该在不引用ASP.NET程序集的程序集中,因此没有机会访问HttpContext编写这么多代码来实现这一点当然不是理想的,但这只是框架限制的结果.例如,在ASP.NET MVC应用程序中,以更好的方式处理这个问题.在这里,您可以单点编写对象图,并且您不必像在WebForms中一样在每个顶级类中解决它们.>好的是,当你必须在页面类构造函数中写一些管道代码时,从对象图中可以使用构造函数注入

猜你在找的C#相关文章