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

nov*_*nto 16 wpf ninject

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

小智 63

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

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

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

  • 控制台应用 - Main
  • WPF - App(除非您使用的是框架,在这种情况下您可以提供自定义引导程序)
  • ASP.NET - 不知道,也许有人可以启发我

免责声明我并不声称自己是权威,Ninject或者DI下面简单地说明了我如何理解这两个对象可以相互结合使用.

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

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

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

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>
Run Code Online (Sandbox Code Playgroud)

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

4)打开App.xaml.cs.这是我们要配置Ninject containerKernel使用Ninject术语的地方.我们override的应用程序OnStartup方法,以便我们可以配置我们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";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

简要介绍:

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

4.2) ConfigureContainer - 告知我们container如何解决我们的具体类型.除了我在这个例子中展示的内容远不止这些,但是,这比我所展示的要多得多.有一些主题,如多重绑定,绑定约定内核模块,您最好从官方文档中了解它.

4.3) ComposeObjects - 删除了StartupUri属性后,App.xaml我们必须通知应用程序我们希望它使用哪个UI控件MainWindow.除了要求我们container使用MainWindow我们之外,我们MainWindow也设置了这个Title属性.同样,您可能希望在此处执行其他任务以进行手动对象组合.

你不必像上面那样将步骤分开,对于这个人为的例子来说,不要打扰它会更有意义.随着应用程序的增长,您开始使用更复杂的东西container,将一些阶段分开开始使container配置更易于管理.这是你的选择.

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>
Run Code Online (Sandbox Code Playgroud)

我不打算解释上面的内容,因为它应该是显而易见的.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我再次简要介绍一下,因为上面发生的事情与配置无关Ninject,它应该再一次显而易见.

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

ConfigureContainer方法中App.xaml.cs我们告知了container我们希望它如何解决依赖关系IWeapon:

container.Bind<IWeapon>().To<Sword>().InTransientScope();
Run Code Online (Sandbox Code Playgroud)

上面讲述了container它遇到依赖关系的任何地方,IWeapon我们希望它提供一个实例Weapon.在请求containerresolve(Get)我们的初始MainWindow控制时,使用以下内容:

Current.MainWindow = this.container.Get<MainWindow>();
Run Code Online (Sandbox Code Playgroud)

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

假设你和我都没有用上面的代码犯过任何错误,按下F5应该启动应用程序,你应该看到一个带有TextBox和的小窗口Button.输入内容TextBox然后按下Button然后你会看到一个MessageBox控制器,告诉你你挥动你的剑就像"mad man"在任何人或你输入的任何东西TextBox.


还有更多工作都NinjectDI比我在这里描述.比如有对主题整本书DI,如这一个由Mark西曼.

希望上面会给你在哪里看哪里去与你的冒险与取得进一步进展的基本出发点NinjectDI.

  • 对不起,这对我来说太过简单了.我们知道我们可以手动解析内核中的组件.WPF世界面临的挑战是通过XAML中的IOC自动解析资源. (6认同)
  • 呃,这是一个高质量的帖子,解释了基本用途的来龙去脉.如果它对你没用,那就继续吧.不需要贬低. (3认同)