如何使用Ninject

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.
  • 好的,所以创建一个NoteCreator.但它的构造函数需要一个IDocumentCreator.
  • 我的配置说,对于一个IDocumentCreator,我应该使用WordDocumentCreator.所以创建一个WordDocumentCreator.
  • 现在我可以传递WordDocumentCreator给NoteCreator.
  • 而现在我可以把它传递NoteCreatorMainWindow.

这个系统的美丽有三个方面.

首先,如果您未能配置某些内容,您将立即知道,因为您的对象是在应用程序运行后立即创建的.Ninject会给你一个有用的错误信息,说明你的IDocumentCreator(例如)无法解决.

其次,如果管理层后来要求用户使用优质文字处理器,那么您所要做的就是

  • 写一个WordPerfectDocumentCreator实现IDocumentCreator.
  • 改变MyAppModule上面,绑定IDocumentCreatorWordPerfectDocumentCreator相反.

第三,如果我想测试我NoteCreator,我不需要传入真实的 WordDocumentCreator(或者我正在使用的任何东西).我可以传递一个假的.这样我就可以编写一个测试,假设我的IDocumentCreator工作正确,并且只测试移动部件NoteCreator本身.我的假装IDocumentCreator只会返回正确的响应,我的测试将确保NoteCreator做正确的事情.

有关如何以这种方式构建应用程序的更多信息,请查看Mark Seemann最近出版的书" .NET中的依赖注入".不幸的是,它不包括Ninject,但它确实涵盖了许多其他DI框架,并且它讨论了如何以我上面描述的方式构建应用程序.

另请参阅 Michael Feathers的"有效使用遗留代码".他谈到了上面的测试方面:如何打破接口并传递假货,以隔离行为并使其受到测试.

  • 对依赖注入以及Ninject都非常好的解释!谢谢,我将它复制到我的Evernote以供进一步参考. (4认同)

Bro*_*ass 22

首先,我需要在我想要使用注入的所有构造函数上使用Inject属性.这看起来像是一个非常蹩脚的设计?

不,你根本不应该这样做.由于您使用ASP.NET MVC,您只需安装Ninject.MVC3 Nuget包.这将使您开始使用NinjectMVC3App_Start文件夹中的类.您可以使用该RegisterServices方法向Ninject注册接口/类.然后,所有与这些接口具有依赖关系的控制器将由Ninject自动解析,不需要Inject属性.

我是否需要创建一个内核然后在注入的类中传递的所有内容?

不 - 你所描述的内容听起来更像是服务定位器模式,而不是依赖注入 - 你需要在构造函数中理想地传递依赖关系,而不是使用内核在特定类中解析它们.应该只有一个中心组合根用于完成解析,它在RegisterServices上面提到的方法中的组合根目录中或者在那里实例化的单独的Ninject模块 - 后面的方法将允许你更多的灵活性和模块性(没有双关语意图) )改变解决依赖关系的方式.

这是一个很好的初学者关于Ninject和MVC3依赖注入的教程.


Rub*_*ink 7

不要忘记有文档,包括一个介绍我觉得非常合适,因为你在Ninject Wiki上提出了一些问题.如果您试图使用Ninject而不是端对端地阅读它,那么您只是烦恼自己.

目录粘贴在书签栏上一会儿.

我还强烈推荐Mark Seemann 在.Net中依赖注入作为基于DI的体系结构的配套书(尽管它没有直接涵盖Ninject).