• MVC进阶之路:依赖注入(Di)和Ninject


    MVC进阶之路:依赖注入(Di)和Ninject

    0X1 什么是依赖注入

      依赖注入(Dependency Injection),是这样一个过程:某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。

                                                          图1

      如图1所示,数据库操作类DataManager中依赖的IDataBase的接口,而不是以来IDataBase的具体实现类,这样的好处是可以让我们的程序具有扩展性:无论我们要使用SqlServer当我们的数据库操作类还是用Mysql,我们需要改动的地方都很少。

    0X2 一个Demo理解Di

      我们创建一个控制台程序,并按照图1中所标识的关系创建四个类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class DataManager
        {
            private IDataBase _database;
            public DataManager(IDataBase database)
            {
                this._database = database;
            }
     
            public void Add()
            {
                _database.Add();
            }
     
            public void Delete()
            {
                _database.Delete();
            }
     
            public void Update()
            {
                _database.Update();
            }
     
            public void Select()
            {
                _database.Select();
            }
        }

    IDataBase接口

    1
    2
    3
    4
    5
    6
    7
    8
    public interface IDataBase
        {
            string DbName { get; }
            void Select();
            void Update();
            void Delete();
            void Add();
        }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class SqlServer : IDataBase
        {
            public string DbName
            {
                get
                {
                    return "SqlServer";
                }
            }
     
            public void Add()
            {
                Console.WriteLine("Add in " + DbName);
            }
     
            public void Delete()
            {
                Console.WriteLine("Delete in " + DbName);
            }
     
            public void Select()
            {
                Console.WriteLine("Select in " + DbName);
            }
     
            public void Update()
            {
                Console.WriteLine("Update in " + DbName);
            }
        }

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public string DbName
            {
                get
                {
                    return "Mysql";
                }
            }
     
            public void Add()
            {
                Console.WriteLine("Add in " + DbName);
            }
     
            public void Delete()
            {
                Console.WriteLine("Delete in " + DbName);
            }
     
            public void Select()
            {
                Console.WriteLine("Select in " + DbName);
            }
     
            public void Update()
            {
                Console.WriteLine("Update in " + DbName);
            }

    如果我们要用Sqlserver作为数据库实现类的话,传统写法我们要New Sqlserver,如下图:

    项目早期使用的是Sqlserver数据库没问题,后来BOSS忽然要改成Mysql数据库,你心里面一想,没问题啊,无非就是把New后面的Sqlserver换成Mysql嘛,简单。于是你就开始改,越改越不对劲,已经你已经发现当前项目已经有好几十个地方用到New Sqlserver(),而剩余的数量往往还是未知的。这个时候你就在想,有没有方法可以让我只需要改一个地方其他地方不用动就可以呢?答案是肯定的,目前这种方法实现有很多种,最简单的无非就是工厂模式。但是,今天,我们不用工厂,我们将使用Ninject来实现这种功能。

    0X3 Ninject的使用

      Ninject是一个IOC容器,用来解决程序中组件的耦合问题,它的目的在于做到最少配置。其他的的IOC工具过于依赖配置文件,需要使用assembly-qualified名称来进行定义,庸长且复杂常常因为打错字而破坏程序。这些是他的优点,也是为什么要选择它。

      

    安装Ninject

      打开Nuget程序包管理控制台输入“Install-Package Ninject”即可安装Ninject。

      

    Ninject使用步骤

      我们一般会在程序启动的入口来创建Ninject的对象负责类型的注册。

    1  static void Main(string[] args)
    2         {
    3             //实例化Ninject对象
    4             IKernel Kerner = new StandardKernel();
    5         }

      使用Ninject对象分两个步骤,第一步是把接口对象或者说被依赖的对象(IDataBase)绑定到Ninject中,然后在为其绑定对应的实例类型(如果要使用SqlServer则就绑定SqlServer)。

     //实例化Ninject对象
     IKernel Kerner = new StandardKernel();
     //绑定对象
     Kerner.Bind<IDataBase>().To<SqlServer>();

      第二步则是通过Ninject的Get方法获取IDataBase的实现类

     var Db = Kerner.Get<IDataBase>(); //由于上面IDataBase绑定的是SqlServer类型,所以这里获取的类型是SqlServer

      上面的代码大家可能体会不到使用Ninject的好处,也没有体会到依赖注入的奥妙所在。依赖注入大致分为三类:接口注入,函数注入,属性注入。我们来通过一个例子来演示属性注入。

      我们增加一个IShowDBInfo的接口类,其有一个Show方法。然后添加一个Show类实现IShowDBInfo接口:

    复制代码
     public class Show1 : IShowDBInfo
        {
            public void Show()
            {
                Console.WriteLine(this.GetType().FullName);
            }
        }
    复制代码

        我们给DataManager添加一个IShowDBInfo属性并增加一个Show()方法:

    复制代码
     public class DataManager
        {
            private IDataBase _database;
            private IShowDBInfo _showDbInfo;
            public DataManager(IDataBase database, IShowDBInfo ishowdbinfo)
            {
                this._database = database;
                _showDbInfo = ishowdbinfo;
            }
           //省略Add,Updata,Delete,Select方法
            public void Show()
            {
                _showDbInfo.Show();
            }
        }     
    复制代码

      在应用程序启动的时候注册IShow类和注册DataManager类并启动程序:

    复制代码
     static void Main(string[] args)
            {
                //实例化Ninject对象
                IKernel Kerner = new StandardKernel();
                //绑定对象
                Kerner.Bind<IDataBase>().To<SqlServer>();
                Kerner.Bind<IShowDBInfo>().To<Show1>();
                Kerner.Bind<DataManager>().ToSelf();
                var dataManager=Kerner.Get<DataManager>();
                dataManager.Show();
                Console.Read();
            }
    复制代码

      从上代码以及运行结果来看,我们只需要在向Ninject实例里面注册对象,然后在其他类中使用的时候我们只需要定义接口就可以了,并不需要实例化对象。这样做的话可以使我们和其他层进行松耦合。

  • 相关阅读:
    官方下载python源码,编译linux版本的python
    bootstrap冻结窗口
    LeetCode之TwoSum
    MyISAM和InnoDB索引实现对比(总结)
    InnoDB的三个关键特性(总结)
    InnoDB与MyISAM总结和对比(总结)
    C++类库开发之导出类设计原则
    C++类库开发详解
    C#各种配置文件使用,操作方法总结
    C/C++代码优化的27条建议
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5672396.html
Copyright © 2020-2023  润新知