阅读目录

 

接口

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

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

  • 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. Vue 组件 生命周期函数mounted

    生命周期函数mounted:页面刷新触发mounted(){ console.log('我在页面刷新时触发');} Tips:使用export default function Add(){},与ex ...

  2. Login failed for user 'xxx'

    今天零晨,正准备晚睡,有一网友在skype求救,意思是说,恢复专案的数据库之后,死活登录不了.出现的错误如下: Insus.NET叫他参考下面方法来做:http://www.cnblogs.com/i ...

  3. javascript 取掉空格自定义函数

    js  取掉空格自定义函数 //取掉左右空格: function trim(str){ return str.replace(/(^\s*)|(\s*$)/g, ""); } // ...

  4. 读《JavaScript权威指南》笔记(四)--数组、函数

    一.数组 1.数组是值的有序集合.每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引.JavaScript数组是无类型的:数组元素可以是任意类型,并且同一个数组中的不同元素也可能有 ...

  5. Go语言技术教程:Redis介绍安装和使用

    Redis介绍 我们日常的开发,数据都需要进行持久化存储,常见的持久化存储有很多种,比如数据库,文件,计算机内存,甚至云服务器等都是持久化存储数据的方式.而就数据库而言,经常又会被人们分为关系型数据库 ...

  6. phpstrom 下载及phpStudy环境配置

    1.下载phpstudy 2.打开 3. 4. 5.网站网址   项目路径 新增         host映射 PHP富文本编辑器 6.https://jingyan.baidu.com/articl ...

  7. ASPxGridView KeyFieldName

    KeyFieldName="查询表的主键名称"

  8. Dynamic Rankings(整体二分)

    Dynamic Rankings(整体二分) 带修区间第k小.\(n,q\le 10^4\). 这次我们旧瓶装新酒,不用带修主席树.我们用整体二分!整体二分是啥东西呢? 二分答案可以解决一次询问的问题 ...

  9. 安装maven时遇到的问题

    配置好环境变量和本地仓库后,在命令行里输入mvn compile,可以显示成功,但是mvn install后就一直失败.显示如下错误: 在idea中显示如下错误: 其实即使显示编译成功,但并没有真正的 ...

  10. redis启动后出现"WARNING you have Transparent Huge Pages (THP) support enabled in your kernel"问题

    问题描述:启动redis后出现:WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This w ...