如何在 WPF 应用程序中使用 Ninject

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20615058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:13:50  来源:igfitidea点击:

How to use Ninject in WPF application

wpfninject

提问by novian kristianto

I'm familiar with MVC but I'm trying to learn WPF with Ninject. Can some one give me some example or reference?

我熟悉 MVC,但我正在尝试使用 Ninject 学习 WPF。有人可以给我一些例子或参考吗?

回答by

As I said in my comment to your OP, all the information you require is available within the Ninject documentation. That said it could be argued that it is easy to get lost within its vast documentation if you are unfamiliar with Ninject and/or DI.

正如我在对您的 OP 的评论中所说,您需要的所有信息都可以在Ninject 文档中找到。也就是说,如果您不熟悉 Ninject 和/或 DI,则很容易迷失在其庞大的文档中。

There are a few tutorials online of which this oneI thought was particularly informative. Whilst it provides an example using a console application, the principles of how Ninjectworks remain the same.

网上有一些教程,我认为其中的这个教程特别有用。虽然它提供了一个使用 a 的示例console application,但Ninject工作原理保持不变。

Irrespective of your application type you configure your container at your application entry point;

无论您的应用程序类型如何,您都可以在应用程序入口点配置容器;

  • Console app - Main
  • WPF - App(unless you are using a framework in which case you may provide a custom bootstrapper)
  • ASP.NET - No idea, perhaps someone could enlighten me
  • 控制台应用程序 - Main
  • WPF - App(除非您使用框架,在这种情况下您可以提供自定义引导程序)
  • ASP.NET - 不知道,也许有人可以启发我


DISCLAIMERI do not claim to be an authority on Ninjector DI, below is simply a quick example of how I understand these two objects canbe used in conjunction with one another.

免责声明我并不声称自己是Ninjector的权威DI,下面只是一个简单的例子,说明我如何理解这两个对象可以相互结合使用。

For example sake, let us work with the examples provided in the Ninject documentation.

例如,让我们使用 Ninject 文档中提供的示例。

1)Create a WPF application named NinjectIoC

1)创建一个名为的WPF应用程序NinjectIoC

2)Use Nuget to add a reference to the Ninjectproject

2)使用Nuget添加对Ninject项目的引用

3)Open App.xamland remove the StartupUriproperty from the Applicationelement so that your App.xamllooks like below:

3)打开App.xamlStartupUriApplication元素中删除属性,使您的App.xaml外观如下所示:

<Application x:Class="NinjectIoC.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>

    </Application.Resources>
</Application>

The reason we do this is because the StartupUriproperty informs the WPFapplication which UI control to initially display when the application starts. We are going to use Ninjectto display our initial UI control.

我们这样做的原因是因为该StartupUri属性通知WPF应用程序在应用程序启动时最初显示哪个 UI 控件。我们将使用Ninject来显示我们的初始 UI 控件。

4)Open App.xaml.cs. This is where we are going to configure the Ninjectcontainer, or Kernelto use Ninjectterminology. We overridethe application OnStartupmethod so that we may configure our containerand subsequently initialise the application as we would like. Update the content of your App.xaml.csto look as follows:

4)打开App.xaml.cs。这是我们要配置Ninjectcontainer,或Kernel使用Ninject术语的地方。我们override使用 applicationOnStartup方法,以便我们可以根据需要配置我们container的应用程序并随后初始化该应用程序。更新你的内容App.xaml.cs如下:

namespace NinjectIoC
{
    using Ninject;
    using System.Windows;

    public partial class App
    {
        private IKernel container;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            ConfigureContainer();
            ComposeObjects();
            Current.MainWindow.Show();
        }

        private void ConfigureContainer()
        {
            this.container = new StandardKernel();
            container.Bind<IWeapon>().To<Sword>().InTransientScope();
        }

        private void ComposeObjects()
        {
            Current.MainWindow = this.container.Get<MainWindow>();
            Current.MainWindow.Title = "DI with Ninject";
        }
    }
}

A brief explination:

简要说明:

4.1)OnStartup - Override theOnStartupmethod so that we may configure ourcontainer` and initialise the application as we desire.

4.1)OnStartup - Override theOnStartupmethod so that we may configure our容器`并根据需要初始化应用程序。

4.2)ConfigureContainer- Inform our containerof how we would like to resolve our concrete types. There is far more to this than I have displayed in this example, however, there is far more to this than I have shown. There are topics such as Multi Binding, Binding Conventionsand Kernel Modulesfor which you are best learning about it from the official documentation.

4.2)ConfigureContainer- 告知我们container我们希望如何解析我们的具体类型。这比我在这个例子中展示的要多得多,但是,这比我展示的要多得多。您最好从官方文档中了解多绑定绑定约定内核模块等主题。

4.3)ComposeObjects- Having removed the StartupUriproperty from App.xamlwe must inform the application which UI control we would like it to use for the MainWindow. Alongside asking our containerto use MainWindowas our MainWindowwe set the Titleproperty too. Again you might want to do other tasks here for manual object composition.

4.3)ComposeObjects-StartupUri从属性中删除后,App.xaml我们必须通知应用程序我们希望它用于MainWindow. 除了要求我们container将其MainWindow用作我们MainWindowTitle属性外,我们也设置了该属性。同样,您可能希望在此处为手动对象组合执行其他任务。

You do not have to separate out the steps as I have above, for this contrived example it would make more sense not to bother. As your application grows and you start to do more sophisticated things with the container, separating some of the stages out begins to make the containerconfiguration more manageable. The choice is yours.

你不必像我上面那样把步骤分开,对于这个人为的例子,不打扰会更有意义。随着您的应用程序的增长并且您开始使用 做更复杂的事情container,分离一些阶段开始使container配置更易于管理。这是你的选择。

5)Next open MainWindow.xaml, then copy and paste the following:

5)接下来打开MainWindow.xaml,然后复制并粘贴以下内容:

<Window x:Class="NinjectIoC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Height="78" Width="362">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" Margin="269,10,0,0" VerticalAlignment="Top" Width="75" Click="Attack"/>
        <TextBox x:Name="Target" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" VerticalAlignment="Top" Width="254"/>
    </Grid>
</Window>

I shall not bother explaining the above as it should be obvious what is going on.

我不会费心解释上述内容,因为很明显发生了什么。

6)Finally open MainWindow.xaml.csand update it as follows:

6)最后打开MainWindow.xaml.cs更新如下:

namespace NinjectIoC
{
    using System.Windows;

    public partial class MainWindow
    {
        private readonly IWeapon weapon;

        public MainWindow(IWeapon weapon)
        {
            this.weapon = weapon;
            InitializeComponent();
        }

        private void Attack(object sender, RoutedEventArgs e)
        {
            this.weapon.Hit(this.Target.Text);
        }
    }

    public class Sword : IWeapon
    {
        public void Hit(string target)
        {
            MessageBox.Show(@"I swing and thrust my sword about like a mad man at " + target);
        }
    }

    public interface IWeapon
    {
        void Hit(string target);
    }
}

Again I will make this brief as what is happening above has nothing to do with the configuration of Ninjectand it should once again be obvious what is happening.

我将再次进行简要说明,因为上面发生的事情与 的配置无关,Ninject并且应该再次清楚正在发生的事情。

The main thing to notice in the above is the argumentthat the MainWindowconstructor expects; IWeapon. You might be asking yourself How does that get resolved as I am not creating a concrete implementation of Weaponanywhere?

主要的一点需要注意的是上面的argumentMainWindow构造函数需要; IWeapon. 您可能会问自己,由于我没有在Weapon任何地方创建具体的实现,如何解决这个问题?

Well during the ConfigureContainermethod in App.xaml.cswe informed the containerhow we would like it to resolve dependencies for IWeapon:

好吧,在ConfigureContainer方法中,App.xaml.cs我们告知了container我们希望它如何解决以下方面的依赖关系IWeapon

container.Bind<IWeapon>().To<Sword>().InTransientScope();

The above tells the containerthat anywhere it encounters a dependency for IWeaponwe would like it to provide an instance of Weapon. Upon requesting the containerresolve (Get) our initial MainWindowcontrol, using the following:

上面告诉container它在任何地方遇到依赖项,因为IWeapon我们希望它提供Weapon. 在请求container解决 ( Get) 我们的初始MainWindow控制后,使用以下内容:

Current.MainWindow = this.container.Get<MainWindow>();

The containertook a look at its constructors and determined the constructor with the most arguments it understood. In this example it was the constructor that required an implementation of IWeaponand oh look, the containerknows how to resolve this dependency because we told it how to do so earlier in ConfigureContainer.

container拍了一下它的构造,并决定用它理解大多数参数的构造函数。在这个例子中,构造函数需要实现,IWeapon哦,看,它container知道如何解决这个依赖关系,因为我们在ConfigureContainer.

Assuming neither you nor I have made any mistakes with the above code, pressing F5should launch the application and you should see a small window with a TextBoxand Button. Enter something in to the TextBoxthen press the Buttonand you should see a MessageBoxcontrol informing you that you swang your sword like a "mad man"at whoever or whatever you entered in the TextBox.

假设你和我都没有对上面的代码犯任何错误,按下F5应该启动应用程序,你应该看到一个带有TextBox和的小窗口Button。输入一些东西,TextBox然后按Button,你应该看到一个MessageBox控制,通知你你挥舞着你的剑,就像"mad man"你在TextBox.



There is far more to both Ninjectand DIthan I have described here. For example there are entire books on the subject of DIsuch as this one by Mark Seeman.

两者都有很多NinjectDI比我在这里描述的要多得多。例如,有关于这个主题的完整书籍,DI例如Mark Seeman 所著的这本书。

Hopefully the above will give you at basic starting point of where to look and where to go to progress further with your adventures with Ninjectand DI.

希望以上内容可以为您提供基本的起点,让您了解在使用Ninject和 进行冒险时应该去哪里以及去哪里进一步发展DI