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. 解 我发现这个工作的最终解决方案是这个帖子中最多的答案: 它看起来像这样(来自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领域的情况 然而,在咨询了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中一样在每个顶级类中解决它们.>好的是,当你必须在页面类构造函数中写一些管道代码时,从对象图中可以使用构造函数注入 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |