我已经阅读了许多关于这个主题的帖子,但没有找到关于如何在不使用服务定位器模式的情况下访问 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 窗体并且需要访问
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 内核的 Controller 工厂,这是唯一引用它的地方。
为了扩展您的特定情况,您的类(class)将接受 ICustomerBusiness
在它的构造函数中,声明它需要一个 ICustomerBusiness
的实例作为它的依赖:
class CustomerBusinessConsumer : ICustomerBusinessConsumer
{
private readonly ICustomerBusiness customerBusiness;
public CustomerBusinessConsumer(ICustomerBusiness customerBusiness)
{
this.customerBusiness = customerBusiness;
}
...
}
现在,无论哪个类使用
ICustomerBusinessConsumer
作为其依赖项,将遵循相同的模式(接受 ICustomerBusinessConsumer
的实例作为其构造函数参数)。你基本上永远不要手动构建您的依赖项 使用 new
(除了特定的异常(exception))。然后,您只需要确保您的类获得它们的依赖项,并且这是您执行此操作的组合根。组合根究竟是什么取决于您正在编写的应用程序的类型(控制台应用程序、WPF 应用程序、Web 服务、MVC Web 应用程序...)
编辑 :让自己熟悉 ASP.NET WebForms 领域中的情况
由于我从未使用过它,因此我不得不查找详细信息。不幸的是,WebForms 要求您在每个 Page 类中都有一个无参数构造函数,因此您不能从对象图的顶部到底部一直使用构造函数注入(inject)。
但是咨询后Mark Seeman在 WebForms 中组合对象的章节中,我可以重新表述如何处理这个框架的低效率,同时仍然符合良好的 DI 实践:
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 的角度来看)是拥有某种“实现者”类,您将向这些类传递页面类的功能。例如,每个 Action 由
MainPage
处理将只中继到它的实现类。这个实现类将是 MainPage
的依赖项并且,与所有其他依赖项一样,将使用容器解决。重要的部分是这些实现类 应该在不引用 ASP.NET 程序集的程序集中因此没有机会访问
HttpContext
关于c# - 如何在不使用服务定位器模式的情况下访问 Ninject.Kernel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11921422/