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()));

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

  • 相关阅读:
    ASP.NET在禁用视图状态的情况下仍然使用ViewState对象【转】
    Atcoder Regular Contest 061 D Card Game for Three(组合数学)
    Solution 「CERC 2016」「洛谷 P3684」机棚障碍
    Solution 「CF 599E」Sandy and Nuts
    Solution 「洛谷 P6021」洪水
    Solution 「ARC 058C」「AT 1975」Iroha and Haiku
    Solution 「POI 2011」「洛谷 P3527」METMeteors
    Solution 「CF 1023F」Mobile Phone Network
    Solution 「SP 6779」GSS7
    Solution 「LOCAL」大括号树
  • 原文地址:https://www.cnblogs.com/uncle_danny/p/6349280.html
Copyright © 2011-2022 走看看