Sac*_*nth 18 c# asp.net-mvc dependency-injection ninject
我今天一直试图使用Ninject,并有几个问题.首先,我需要在我想要使用注入的所有构造函数上使用Inject属性.这看起来像是一个非常蹩脚的设计?我是否需要创建一个内核然后在注入的类中传递的所有内容?
Rya*_*ndy 58
开始使用Ninject的最佳方法是从小处着手.寻找一个new
.
在应用程序中间的某个地方,您正在另一个类中创建一个类.这意味着你正在创建一个依赖项.依赖注入是指通常通过构造函数传递这些依赖项,而不是嵌入它们.
假设您有这样的类,用于在Word中自动创建特定类型的注释.(这类似于我最近在工作中完成的一个项目.)
class NoteCreator
{
public NoteHost Create()
{
var docCreator = new WordDocumentCreator();
docCreator.CreateNewDocument();
[etc.]
Run Code Online (Sandbox Code Playgroud)
WordDocumentCreator
是一个处理在Microsoft Word中创建新文档的细节的类(创建Word的实例等).我的课,NoteCreator
,依赖于WordDocumentCreator
执行工作.
麻烦的是,如果有一天我们决定转移到一个优秀的文字处理器,我必须找到WordDocumentCreator
实例化的所有地方并改变它们来实例化WordPerfectDocumentCreator
.
现在想象我改变我的类看起来像这样:
class NoteCreator
{
WordDocumentCreator docCreator;
public NoteCreator(WordDocumentCreator docCreator) // constructor injection
{
this.docCreator = docCreator;
}
public NoteHost Create()
{
docCreator.CreateNewDocument();
[etc.]
Run Code Online (Sandbox Code Playgroud)
我的代码没有那么大改变; 我在Create
方法中所做的就是删除行new
.但现在我正在注入我的依赖.让我们做一个小小的改变:
class NoteCreator
{
IDocumentCreator docCreator;
public NoteCreator(IDocumentCreator docCreator) // change to interface
{
this.docCreator = docCreator;
}
public NoteHost Create()
{
docCreator.CreateNewDocument();
[etc.]
Run Code Online (Sandbox Code Playgroud)
我没有传递具体的内容 WordDocumentCreator
,而是使用方法提取了一个IDocumentCreator
接口CreateNewDocument
.现在我可以传入任何实现该接口的类,所有NoteCreator
必须做的就是调用它知道的方法.
现在是棘手的部分.我现在应该在我的应用程序中出现编译错误,因为我正在创建NoteCreator
一个不再存在的无参数构造函数.现在我也需要提取这种依赖性.换句话说,我经历了与上面相同的过程,但现在我将它应用于创建新的类NoteCreator
.当您开始提取依赖项时,您会发现它们会"冒泡"到应用程序的根目录,这是您应该引用DI容器的唯一位置(例如Ninject).
我需要做的另一件事是配置Ninject.必不可少的是一个看起来像这样的类:
class MyAppModule : NinjectModule
{
public override void Load()
{
Bind<IDocumentCreator>()
.To<WordDocumentCreator>();
Run Code Online (Sandbox Code Playgroud)
这告诉Ninject当我尝试创建一个类,在某个地方,需要一个IDocumentCreator
,它应该创建一个WordDocumentCreator
并使用它.Ninject经历的过程看起来像这样:
MainWindow
.它的构造函数需要一个NoteCreator
.IDocumentCreator
.IDocumentCreator
,我应该使用WordDocumentCreator
.所以创建一个WordDocumentCreator
.WordDocumentCreator
给NoteCreator.NoteCreator
给MainWindow
.这个系统的美丽有三个方面.
首先,如果您未能配置某些内容,您将立即知道,因为您的对象是在应用程序运行后立即创建的.Ninject会给你一个有用的错误信息,说明你的IDocumentCreator
(例如)无法解决.
其次,如果管理层后来要求用户使用优质文字处理器,那么您所要做的就是
WordPerfectDocumentCreator
实现IDocumentCreator
.MyAppModule
上面,绑定IDocumentCreator
到WordPerfectDocumentCreator
相反.第三,如果我想测试我NoteCreator
,我不需要传入真实的 WordDocumentCreator
(或者我正在使用的任何东西).我可以传递一个假的.这样我就可以编写一个测试,假设我的IDocumentCreator
工作正确,并且只测试移动部件NoteCreator
本身.我的假装IDocumentCreator
只会返回正确的响应,我的测试将确保NoteCreator
做正确的事情.
有关如何以这种方式构建应用程序的更多信息,请查看Mark Seemann最近出版的书" .NET中的依赖注入".不幸的是,它不包括Ninject,但它确实涵盖了许多其他DI框架,并且它讨论了如何以我上面描述的方式构建应用程序.
另请参阅 Michael Feathers的"有效使用遗留代码".他谈到了上面的测试方面:如何打破接口并传递假货,以隔离行为并使其受到测试.
Bro*_*ass 22
首先,我需要在我想要使用注入的所有构造函数上使用Inject属性.这看起来像是一个非常蹩脚的设计?
不,你根本不应该这样做.由于您使用ASP.NET MVC,您只需安装Ninject.MVC3 Nuget包.这将使您开始使用NinjectMVC3
App_Start文件夹中的类.您可以使用该RegisterServices
方法向Ninject注册接口/类.然后,所有与这些接口具有依赖关系的控制器将由Ninject自动解析,不需要Inject属性.
我是否需要创建一个内核然后在注入的类中传递的所有内容?
不 - 你所描述的内容听起来更像是服务定位器模式,而不是依赖注入 - 你需要在构造函数中理想地传递依赖关系,而不是使用内核在特定类中解析它们.应该只有一个中心组合根用于完成解析,它在RegisterServices
上面提到的方法中的组合根目录中或者在那里实例化的单独的Ninject模块 - 后面的方法将允许你更多的灵活性和模块性(没有双关语意图) )改变解决依赖关系的方式.
这是一个很好的初学者关于Ninject和MVC3依赖注入的教程.
不要忘记有文档,包括一个介绍我觉得非常合适,因为你在Ninject Wiki上提出了一些问题.如果您试图使用Ninject而不是端对端地阅读它,那么您只是烦恼自己.
将目录粘贴在书签栏上一会儿.
我还强烈推荐Mark Seemann 在.Net中的依赖注入作为基于DI的体系结构的配套书(尽管它没有直接涵盖Ninject).