阅读目录

 

接口

在说依赖注入之前,先了解下什么是接口。

我们在学编程的时候都知道,接口的相关规则:(来源百度百科

  • 1. 接口是一个引用类型,通过接口可以实现多重继承。
  • 2. C#中接口的成员不能有new、public、protected、internal、private等修饰符。
  • 3. 接口中只能声明"抽象"成员(所以不能直接下一步对接口进行实例化(即不能使用new操作符声明一个接口的实例对 象)),而不能声明共有的域或者私有的成员变量。
  • 4. 接口声明不包括数据成员,只能包含方法、属性、事件、索引等成员。
  • 5. 接口名称一般都以“I”作为首字母(当然不这样声明也可以),这也是接口和类的一个区别之一。
  • 6. 接口成员的访问级别是默认的(默认为public),所以在声明时不能再为接口成员指定任何访问修饰符,否则 编译器会报错。
  • 7. 接口成员不能有static、abstract、override、virtual修饰符,使用new修饰符不会报错,但会给出警告说不需要关键字new。
  • 8. 在声明接口成员的时候,不准为接口成员编写具体的可执行代码,也就是说,只要在对接口进行声明时指明接口的成员名称和参数就可以了。
  • 9. 接口一旦被实现,实现类必须实现接口中的所有成员,除非实现类本身是抽象类(通过具体的可执行代码实现接口抽象成员的操作)。

很多时候看到这么多的概念,也是云里雾里的。项目中的接口使用也是按照老代码依葫芦画瓢。如果是自己练手的代码或者demo,也是没有使用接口。(给自己的借口就是,我只是做些小的东西,根本就不需要使用接口一样可以跑很溜啊。)

接口是什么?(说说我自己的理解,不一定对)

接口就是为了更换一个可能过时或者错误的实现而准备的。就想我们的电脑,里面就到处都是接口。usb、内存条、硬盘、电池、键盘...等等都是有各自的接口。我们可以通过硬盘接口换个更大的硬盘或者换个更快的固态硬盘。如果键盘坏了,也可以通过键盘接口买个新的键盘换上去。这就是接口明显的好处。接口也可以理解成大家的约定。约定了特定接口的大小功能等等。

那么我们写代码也是一样,在某些地方可能会经常变动,逻辑会经常修改的地方使用接口约定。下面我们就用硬盘的接口来做示例吧。

首先定义一个硬盘接口。(一个name属性,一个读一个写的方法)

/// <summary>
/// 硬盘接口
/// </summary>
interface IHardDisk
{
/// <summary>
/// 硬盘的名字属性
/// </summary>
string name { get; }
/// <summary>
/// 读取数据方法
/// </summary>
void read();
/// <summary>
/// 写数据
/// </summary>
void write(string str);
}

然后我们买了一个200G的硬盘,它实现了上面的接口。

public class HardDisk200 : IHardDisk
{
public string name
{
get
{
return "我是200G硬盘";
}
} public void read()
{
Console.WriteLine("我可以写入数据哦....");
} public void write(string str)
{
Console.WriteLine(str);
} }

在电脑中使用这个硬盘。

static void Main(string[] args)
{
//这里的h就是一个插在接口上的设备
IHardDisk h = new HardDisk200();
h.read();
h.write(h.name + ",我可以写入数据哦"); Console.ReadKey();
}

某天,我们发现这个硬盘太小了,需要换个1T的。(那样我们可以存很多很多的电影>_<),那么买吧。

public class HardDisk1T : IHardDisk
{
public string name
{
get
{
return "我是1T硬盘";
}
}
public void read()
{
Console.WriteLine("我可以写入数据哦....");
}
public void write(string str)
{
Console.WriteLine(str);
}
}

然后怎么使用了?只要在电脑上的接口直接插上新的硬盘就ok了,其他的什么地方都不用改。

这就是使用接口的好处。当某天我们发现电脑太慢了,我们可以买个固态硬盘,直接在接口使用的地方换上就可以了,其他地方完全不用修改。

这样,我们就可以在不同时期或不同情况下灵活更换继承实现了接口的任何对象,而不用修改其它地方的代码。

又或者说,实现了这个接口的设备就是存储设备。(它一定有存也一定可以储,也就是一定可以写入和读出数据。)

依赖注入

在我们了解了什么是接口之后,我们接着来说说今天主要的主题吧。

还是先从例子入手,且是我们学过编程都知道的例子,三层。(什么?你不知道什么是三层?那你别看了,先补习了再过来)

我们先来写个简单的三层伪代码。

DAL:

 public class DALMsSqlHelper
{
public int add(string str)
{
//...省略具体实现
return 1;
}
//...省略具体实现,如修改 删除 查询
}

BLL:

public class BLLAddStudent
{
DALMsSqlHelper mssql = null;
public BLLAddStudent()
{
mssql = new DALMsSqlHelper();
}
public int addStudent()
{
string str = ""; //...省略具体实现
return mssql.add(str);
}
}

UI:

 public class UI
{
BLLAddStudent s = new BLLAddStudent();
public UI()
{
s.addStudent();
}
}

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

就在系统用了一年之后,老板说:”听说oracle很牛逼,大公司都是用的oracle。咱们也换上吧。“。 好,那就换吧。

DAL:

public class DALOracleSqlHelper
{
public int addOracle(string str)
{
//...省略具体实现
return 1;
}
//...省略具体实现,如修改 删除 查询
}

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

BLL:

public class BLLAddStudent
{
DALOracleSqlHelper mssql = null;
public BLLAddStudent()
{
mssql = new DALOracleSqlHelper();
}
public int addStudent()
{
string str = ""; //...省略具体实现
return mssql.addOracle(str);
}
}

不就换个数据库吗?为何修改这么大,要是老板哪天又要换回oracle怎么办?这得好好想个办法。

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

public interface ISqlHelper
{
int add();
    //...省略具体实现,如修改 删除 查询
 }

DAL修改如下:

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

BLL:

 public class BLLAddStudent
{
ISqlHelper mssql = null;
public BLLAddStudent(ISqlHelper sqlhelper)
{
mssql = sqlhelper;
}
public int addStudent()
{
string str = ""; //...省略具体实现
return mssql.add(str);
}
}

UI:

public class UI
{
public UI()
{
ISqlHelper sqlhelper = new DALOracleSqlHelper();
BLLAddStudent s = new BLLAddStudent(sqlhelper);
s.addStudent();
}
}

如果哪天老板又要换会mssql怎样办。那么仅仅只要修改UI

又过一年之后,因为公司不景气。所以又来需求了。老板:”唉,算了。我们还是用mysql吧。免费的,为公司节省点“。那么我们又要修改了。

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

DAL:

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

UI实现如下:

public class UI
{
public UI()
{
ISqlHelper sqlhelper = new DALMySqlHelper();
BLLAddStudent s = new BLLAddStudent(sqlhelper);
s.addStudent();
}
}

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

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

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

这里就可以用到我们上篇讲的反射了。

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

[巩固C#] 三、依赖注入是什么?的更多相关文章

  1. spring-framework-中文文档三:依赖注入DI

    5.4依赖性 典型的企业应用程序不包含单个对象(或Spring的说法中的bean).即使最简单的应用程序也有几个对象一起工作来展示最终用户将其视为一个连贯的应用程序.下一节将介绍如何从定义许多独立的b ...

  2. 依赖注入(DI)与控制反转(IOC)基础知识

    依赖注入(DI)与控制反转(IOC)基础知识 一.什么是依赖注入? 依赖注入英文是Dependcy Injection简写DI,依赖注入会将所依赖的对象自动交由目标对象使用,而不是让对象自己去获取. ...

  3. ASP.NET Core 中文文档 第三章 原理(10)依赖注入

    原文:Dependency Injection 作者:Steve Smith 翻译:刘浩杨 校对:许登洋(Seay).高嵩 ASP.NET Core 的底层设计支持和使用依赖注入.ASP.NET Co ...

  4. 在ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC4中,为了在解开Controller和Model的耦合,我们通常需要在Controller激活系统中引入IoC,用于处理用户请求的 Controller,让Controller ...

  5. Spring依赖注入三种方式详解

    在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...

  6. Spring的依赖注入(DI)三种方式

    Spring依赖注入(DI)的三种方式,分别为: 1.  接口注入 2.  Setter方法注入 3.  构造方法注入 下面介绍一下这三种依赖注入在Spring中是怎么样实现的. 首先我们需要以下几个 ...

  7. Spring依赖注入的三种方式

    看过几篇关于Spring依赖注入的文章,自己简单总结了一下,大概有三种方式: 1.自动装配 通过配置applicationContext.xml中的标签的default-autowire属性,或者标签 ...

  8. spring4之依赖注入的三种方式

    1.Setter注入 <bean id="helloWorld" class="com.jdw.spring.beans.HelloWorld"> ...

  9. SSH深度历险记(八) 剖析SSH核心原则+Spring依赖注入的三种方式

           于java发育.一类程序猿必须依靠类的其他方法,它是通常new依赖类的方法,然后调用类的实例,这样的发展问题new良好的班统一管理的例子.spring提出了依赖注入的思想,即依赖类不由程 ...

  10. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

随机推荐

  1. Hibernate常见异常总结

    系统配置 1.没有查找到src目录下的hibernate.cfg.xml Exception in thread "main" org.hibernate.HibernateExc ...

  2. ajax上传json串格式的数据的处理 以及 js操作dom的另一种方式

  3. centos-7.4_ceph-12.2.4部署

    centos-7.4_ceph-12.2.4部署: 前言: 基于centos7.4安装ceph-luminous的主要步骤有一下几点: 1.安装centos7.4的系统,并配置网卡 2.安装前的环境配 ...

  4. 配置IIS使用Python 与常见问题解决

    打开IIS管理器 选择功能视图,然后选择ISAPI和CGI限制 打开后,在右侧操作,点击添加,会出现下图所示 按图中提示填写相应部分,在选择路径时,默认可能是dll文件,改成全部文件即可,然后再选择p ...

  5. Python——用socket和线程实现全双工收发数据

    用socket和线程实现全双工收发数据 1.基础知识 Socket(套接字) 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.由此知道套接字是全双工的. 线程 ...

  6. P4011 孤岛营救问题

    \(\color{#0066ff}{题目描述}\) 1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩.瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克 ...

  7. P4799 [CEOI2015 Day2]世界冰球锦标赛

    \(\color{#0066ff}{题目描述}\) 今年的世界冰球锦标赛在捷克举行.Bobek 已经抵达布拉格,他不是任何团队的粉丝,也没有时间观念.他只是单纯的想去看几场比赛.如果他有足够的钱,他会 ...

  8. PAT天梯赛L1-054 福到了

    题目链接:点击打开链接 "福"字倒着贴,寓意"福到".不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出.这里要处理的每个汉字是由一个 N x N 的 ...

  9. javascript的offset、client、scroll、screen使用方法

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAHuCAYAAABpm/53AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjw

  10. [JavaScript]Prototype继承

    JavaScript相对于其他的编程语言是比较简单的,只要吃透了Prototype和Closure(闭包),基本上就可以说精通JavaScript了. JavaScript里如何实现向Java语言的O ...