用Delphi控件来理解C#的接口和依赖注入

Delphi 最让开发者喜欢的地方就是组件可视化。拖拽组件,关联一下组件,不用代码就搞定好多组件(类)关联上的东西,不同类之间互相引用,传递数据的实现。

拖出几个组件,配置一下组件之间的引用关联。

 修改Connection组件里要连接的数据库类型。

 

以上操作,都是Delphier非常习以为常的事情,没感觉有什么大不了。增删改查询可以直接使用DBGrid上组件内置的功能都能直接实现。

要切换mssql oracle sqlite pg,在Connection组件里面换一下DriverId就行了。

 

但是,对于C#来说,刚开始学习的时候通常例子都是这样的。

DAL:

    public class DALMsSqlHelper
    {     
       Connection = 'mssql=DB=IP=PWD=';
      public int add(Data data)
      {         
        //  省略具体实现
        return 1;
      }     
      public int edit(Data data)
      {         
        //  省略具体实现
        return 1;
      }  
      public int del(Data data)
      {         
        //  省略具体实现
        return 1;
      }        
    }

 

BLL:

    public class BLLStudent
    {
      DALMsSqlHelper mssql = null;    
      public BLLStudent()  //构造函数
      {
           //DAL层
        mssql = new DALMsSqlHelper();
      }    

      public int addStudent(Data data)
      {        
           //...省略具体实现
        return mssql.add(data);
      }
      public int editStudent(Data data)   
       { //...省略具体实现     
           return mssql.edit(data);   
       }
      public int delStudent(Data data)   
       { //...省略具体实现     
           return mssql.del(data);   
       }
    } 

 

UI:

    public class UI
    {
      BLLStudent std = new BLLStudent();     

      public UI()
      {
        std.addStudent(data);

           std.editStudent(data);

           std.delStudent(data);
      }
    }

 

应该说简单得不能在简单的三层。

 

如果要换Oracel数据库呢?那要修改代码才行。

 

DAL:

    public class DALOracleSqlHelper
    {    
        Connection = 'oracel=DB=IP=PWD=';

      public int add(Data data)
      {         
        //  省略具体实现
        return 1;
      }     
      public int edit(Data data)
      {         
        //  省略具体实现
        return 1;
      }  
      public int del(Data data)
      {         
        //  省略具体实现
        return 1;
      }  
    }

 

显然BLL也要进行修改,因为BLL引用了DAL的查询类。

BLL:

    public class BLLStudent
    {
      DALOracleSqlHelper orasql = null;    
      public BLLAddStudent()  //构造函数
      {
           //Orcale数据库 DAL层
        orasql = new DALOracleSqlHelper();
      }    

      public int addStudent(Data data)
      {        
        //  省略具体实现
        return orasql.add(str);
        }
      public int editStudent(Data data)
      {        
        //  省略具体实现
        return orasql.edit(str);
        }
      public int delStudent(Data data)
      {        
        //  省略具体实现
        return orasql.del(str);
        }
    }

 

UI:不变。

 

不就换个oracle数据库吗?为何修改这么大,要是哪天又要换回mssql怎么办?

 

首先,我们定义一个数据访问的接口。

    public interface ISqlHelper
    {    
       int add();
       int edit();
       int del();
    }

 

DAL修改如下:

   public class DALMsSqlHelper : ISqlHelper
   {    
      public int add(Data data)
      {        
        //  省略具体实现
        return 1;
      }   
       //  省略具体实现,如修改 删除 查询
   }


   public class DALOracleSqlHelper : ISqlHelper
   {    
      public int add(Data data)
      {        
        //  省略具体实现
        return 1;
      }
        //  省略具体实现,如修改 删除 查询
   }

 

BLL修改如下:

    public class BLLAddStudent
    {
      ISqlHelper sqlHelper = null;     

      public BLLAddStudent(ISqlHelper sqlhelper)
      {
        this.sqlHelper = sqlhelper;
      }     

      public int addStudent(Data data)
      {         
        return sqlHelper.add(data);
      }
        //省略具体实现,修改,删除,查询
    }

 

UI修改如下:

    public class UI
    {      
      public UI()
      {
            //创建Helper接口对象
        ISqlHelper sqlhelper = new DALOracleSqlHelper();
        BLLStudent std = new BLLStudent(sqlhelper);
        std.addStudent(data);
      }
    }

 

如果哪天又要换会mssql怎样办。那么仅仅只要修改UI 创建Helper接口对象为 DALMsSqlHelper

    public class UI
    {      
      public UI()
      {
        ISqlHelper sqlhelper = new DALMsSqlHelper();  //修改Helper接口对象
        BLLStudent std = new BLLStudent(sqlhelper);
        std.addStudent(data);
      }
    }

 

如果又换数据库,修改为连接MySql呢?

首先需要重新写个mysql的实现。

DAL: 

    public class DALMySqlHelper : ISqlHelper
    {    
      public int add(Data data)
      {        
        //  省略具体实现
        return 1;
      }    
      //  省略具体实现,如修改 删除 查询
    }

 

UI实现如下: 

    public class UI
    {      
      public UI()
      {
        ISqlHelper sqlhelper = new DALMySqlHelper();
        BLLStudent std = new BLLStudent(sqlhelper);
        std.addStudent(str);
      }
    }

 

有没有发现。我们只是在DAL新增了一个mysql的实现和修改了下UI层的接口构造。其中BLL我们根本就没有动它的。 

是的,这样我们就可以说这里的UI对于BLL来说就是”依赖注入“,BLL对于UI来说就是”控制反转“。所以,我觉得依赖注入和控制反转是同一个概念,只是立场不同。 

上面,我们看到了虽然BLL层已经不需要变动就可以新增一个数据源的访问。那么我们能不能也不修改UI层呢?

 

这里就可以用到反射了。

 

 

然后,不管想怎么折腾,我只需要改改配置文件就可以了。甚至都不用动代码。(如果需要新增一个数据源操作,也只要重新实现下,然后改改配置文件)。

 

posted @ 2022-05-14 12:05  K.R  阅读(204)  评论(0编辑  收藏  举报