我目前在需要使用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; } ...
下面接受的答案间接导致我找到这个解决方案.
解决方法
例如,在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中一样在每个顶级类中解决它们.>好的是,当你必须在页面类构造函数中写一些管道代码时,从对象图中可以使用构造函数注入