zoukankan      html  css  js  c++  java
  • Ninject之旅之十二:Ninject在Windows Form程序上的应用(附程序下载)

    摘要:

    下面的几篇文章介绍如何使用Ninject创建不同类型的应用系统。包括:

    • Windows Form应用系统
    • ASP.NET MVC应用系统
    • ASP.NET Web Form应用系统

    尽管对于不同类型的应用系统,Ninject向应用组件注入依赖项的方式是相同的。但是根据不同应用系统架构不同,创建这些应用系统是不同的。一些新的框架例如ASP.NET MVC被设计成支持DI的,然而一些旧的框架例如ASP.NET是不支持所有DI模式。

    前面已经介绍了Ninject提供的大多数功能,下面我们将在一个工程里应用这些功能。我们将实现一些应用,每一个应用都包含一个数据访问层,一个业务层,一个表现层,前面两层将在所有应用中共享。

    程序下载

    准备工作

    1. 在网上下载Northwind数据库,并Restore或Attach到本地数据库。

    2. 用Visual Studio 2015创建空解决方案Demo.Northwind。

    3. 在解决方案Demo.Northwind里创建数据访问层工程:Demo.Northwind.Core。

    在工程Demo.Northwind.Core内,用NuGet Manager添加引用EntityFramework和Ninject。

     在工程Demo.Northwind.Core内添加如下文件/文件夹。

    Customer.cs:

     1 namespace Demo.Northwind.Core.Model
     2 {
     3     public class Customer
     4     {
     5         public string CustomerID { get; set; }
     6 
     7         public string CompanyName { get; set; }
     8 
     9         public string City { get; set; }
    10 
    11         public string PostalCode { get; set; }
    12 
    13         public string Phone { get; set; }
    14     }
    15 }

    ICustomerRepository.cs:

     1 using Demo.Northwind.Core.Model;
     2 using System.Collections.Generic;
     3 
     4 namespace Demo.Northwind.Core.Interface
     5 {
     6     public interface ICustomerRepository
     7     {
     8         IEnumerable<Customer> GetAll();
     9 
    10         Customer Get(string customerID);
    11 
    12         void Add(Customer customer);
    13     }
    14 }

    NorthwindContext.cs:

     1 using Demo.Northwind.Core.Model;
     2 using System.Data.Entity;
     3 
     4 namespace Demo.Northwind.Core.SqlDataAccess
     5 {
     6     public class NorthwindContext : DbContext
     7     {
     8         public NorthwindContext() { }
     9 
    10         public DbSet<Customer> Customers { get; set; }
    11     }
    12 }

    SqlCustomerRepository.cs:

     1 using System.Collections.Generic;
     2 using Demo.Northwind.Core.Interface;
     3 using Demo.Northwind.Core.Model;
     4 
     5 namespace Demo.Northwind.Core.SqlDataAccess
     6 {
     7     public class SqlCustomerRepository : ICustomerRepository
     8     {
     9         private readonly NorthwindContext _context;
    10 
    11         public SqlCustomerRepository()
    12         {
    13             _context = new NorthwindContext();
    14         }
    15 
    16         public void Add(Customer customer)
    17         {
    18             _context.Customers.Add(customer);
    19             _context.SaveChanges();
    20         }
    21 
    22         public Customer Get(string customerID)
    23         {
    24             return _context.Customers.Find(customerID);
    25         }
    26 
    27         public IEnumerable<Customer> GetAll()
    28         {
    29             return _context.Customers;
    30         }
    31     }
    32 }

    创建工程Demo.Northwind.Winforms

    Windows Forms是实现DI的一个最直接的应用系统类型。像Console应用程序一样,它不需要特别的Ninject配置。在Program类里的Main方法注册依赖项,框架里的组件例如Form类不需要一个无参数的构造函数,这使得实现构造函数注入变得很简单。

    1. 在工程Demo.Northwind.Winforms内使用NutGet Manager添加如下引用:

    2. 在工程Demo.Northwind.Winforms内添加到Demo.Northwind.Core的引用。

    修改App.config,添加数据库连接字符串:

    <connectionStrings>
        <add name="NorthwindContext" providerName="System.Data.SqlClient" connectionString="Data Source=localhost;Initial Catalog=NORTHWND;Integrated Security=True" />
      </connectionStrings>

    3. 在MainForm里添加一个DataGrid控件,一个BindingSource控件。绑定DataGrid控件的数据源到BindingSource控件。

    代码:

     1 using Demo.Northwind.Core.Interface;
     2 using Demo.Northwind.Core.Model;
     3 using System;
     4 using System.Linq;
     5 using System.Windows.Forms;
     6 
     7 namespace Demo.Northwind.Winforms
     8 {
     9     public partial class MainForm : Form
    10     {
    11         private readonly ICustomerRepository _repository;
    12 
    13         public MainForm(ICustomerRepository repository)
    14         {
    15             this._repository = repository;
    16             InitializeComponent();
    17         }
    18 
    19         private void MainForm_Load(object sender, EventArgs e)
    20         {
    21             LoadCustomers();
    22         }
    23 
    24         private void LoadCustomers()
    25         {
    26             var customers = _repository.GetAll();
    27             customerBindingSource.DataSource = customers.ToList<Customer>();
    28         }
    29     }
    30 }

    ICustomerRepository是这个类唯一的依赖项,在构造函数内引入和注入。

    4. 既然MainForm的构造函数注入了一个ICustomerRepository对象,需要在Ninject中完成依赖注入,并使用kernel.Get<CustomerForm>()得到MainForm窗口对象,修改Program.cs:

     1 using System;
     2 using System.Windows.Forms;
     3 using Ninject;
     4 using Ninject.Extensions.Conventions;
     5 
     6 namespace Demo.Northwind.Winforms
     7 {
     8     static class Program
     9     {
    10         /// <summary>
    11         /// The main entry point for the application.
    12         /// </summary>
    13         [STAThread]
    14         static void Main()
    15         {
    16             Application.EnableVisualStyles();
    17             Application.SetCompatibleTextRenderingDefault(false);
    18 
    19             using (var kernel = new StandardKernel())
    20             {
    21                 kernel.Bind(x => x.FromAssembliesMatching("Demo.Northwind.*")
    22                     .SelectAllClasses()
    23                     .BindAllInterfaces());
    24 
    25                 var mainForm = kernel.Get<MainForm>();
    26                 Application.Run(mainForm);
    27             }
    28         }
    29     }
    30 }

    5. 如果要在MainForm窗口上加一个“Create”按钮,点击按钮打开一个CustomerForm窗口用来添加新Customer并保存到数据库。CustomerForm窗口类也应该在构造函数中注入一个ICustomerRepository对象。

    新建Windows Form:CustomerForm。

     

    代码:

     1 using Demo.Northwind.Core.Interface;
     2 using Demo.Northwind.Core.Model;
     3 using System;
     4 using System.Windows.Forms;
     5 
     6 namespace Demo.Northwind.Winforms
     7 {
     8     public partial class CustomerForm : Form
     9     {
    10         private readonly ICustomerRepository repository;
    11 
    12         public CustomerForm(ICustomerRepository repository)
    13         {
    14             this.repository = repository;
    15             InitializeComponent();
    16             customerBindingSource.Add(new Customer());
    17         }
    18 
    19         private void saveButton_Click(object sender, EventArgs e)
    20         {
    21             customerBindingSource.EndEdit();
    22             var customer = customerBindingSource.Current as Customer;
    23             repository.Add(customer);
    24             this.DialogResult = DialogResult.OK;
    25         }
    26 
    27         private void closeButton_Click(object sender, EventArgs e)
    28         {
    29             this.DialogResult = DialogResult.Cancel;
    30         }
    31     }
    32 }

    6. 在MainForm.cs中添加Create按钮事件:createButton_Click:

    1         private void createButton_Click(object sender, EventArgs e)
    2         {
    3             
    4         }

    问题来了,CustomerForm窗口类只有一个注入ICustomerRepository对象的构造函数,不能使用new无参数的构造函数创建CustomerForm窗口类对象,也不能在MainForm窗口类里再新创建一个kernal对象,使用Get方法得到CustomerForm对象。

    因此,我们怎么办呢?这个时候应该使用Ninject动态工厂。多亏了Ninject工厂功能,我们只需要简单地定义如下的接口:

    1 using System.Windows.Forms;
    2 
    3 namespace Demo.Northwind.Winforms
    4 {
    5     public interface IFormFactory
    6     {
    7         T Create<T>() where T : Form;
    8     }
    9 }

    在MainForm类里添加IFormFactory对象:

    private readonly IFormFactory _formFactory;

    修改MainForm类createButton_Click事件:

    1         private void createButton_Click(object sender, EventArgs e)
    2         {
    3             var customerForm = _formFactory.Create<CustomerForm>();
    4             if (customerForm.ShowDialog(this) == DialogResult.OK)
    5             {
    6                 LoadCustomers();
    7             }
    8         }

    修改MainForm类构造函数,添加IFormFactory对象注入:

    1         public MainForm(ICustomerRepository repository, IFormFactory formFactory)
    2         {
    3             this._repository = repository;
    4             this._formFactory = formFactory;
    5             InitializeComponent();
    6         }

    最后是在Program类的Main方法里添加注册我们的动态工厂服务:

    1             kernel.Bind(x => x.FromThisAssembly()
    2                 .SelectAllInterfaces()
    3                 .EndingWith("Factory")
    4                 .BindToFactory()
    5                 .Configure(c => c.InSingletonScope()));

     运行系统,测试系统运行情况。

  • 相关阅读:
    今天刚开通博客,很开心
    ZYNQ双核AMP开发详解(USE_AMP -DUSE_AMP=1 含义和作用详解)
    赛灵思机器学习套件(ML Suite) v1.4 DPU, DNNK
    petalinux add pre-build application to rootfs compile faliure solution
    如何用SDK生成device tree
    Zynq UltraScale+ MPSoC device tree 中 CCF中 clock output数字映射表
    Zynq ZC702平台 QSPI + eMMC实现
    Zynq ZC702平台 Linux + Baremetal AMP实现(一)【快速启动CPU1】
    第五章 任务执行
    第四章 闭锁
  • 原文地址:https://www.cnblogs.com/uncle_danny/p/6349280.html
Copyright © 2011-2022 走看看