目录
一、引言
IoC-Invertion of Control,即控制反转,是一种程序设计思想。
先初步了解几个概念:
依赖(Dependency):就是有联系,有地方使用它就是有依赖它。
依赖倒置原则(DIP):设计模式六大原则之一,是一种软件架构设计原则。
控制反转(IoC):一种软件设计原则,上层对下层的依赖(即底层模块的获得)交给第三方。
IoC容器:依赖注入的框架,用来映射依赖,管理对象的创建和生存周期。
依赖注入(DI):实现IoC的一种方式、手段。
反射:可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。
二、基础
1)依赖
简单来说:B里面new一个A,那么B依赖A
举例如下:
public class Program
{
static void Main(string[] args)
{
B b = new B(); //客户端依赖B
A a = new A(); //客户端依赖A
b.Run();
Console.Read();
}
}
//A
public class A
{
public string Show()
{
return "我是A";
}
}
//B
public class B
{
private A a = new A(); //B依赖A
public void Run()
{
Console.WriteLine($"今天是{a.Show()}");
}
}
我们可以从中找到三个依赖关系:
客户端依赖对象B;
客户端依赖对象A;
B依赖对象A;
2)DIP依赖倒置原则
依赖倒置原则DIP,主要有两层含义:
- 高层次的模块不应该依赖低层次的模块,两者都应该依赖依赖低层次的模块的抽象。
- 抽象不应该依赖于具体,具体应该依赖于抽象。
我们先来解释第一句话:模块之间的依赖是通过抽象发生的,实现类之间不应该发生直接的依赖关系,他们的依赖关系应该通过接口或者抽象类产生。
在来解释第二句话:举个例子,假如我们要写BLL层的代码,直接就去实现了功能,等到开发完成以后发现没有使用依赖倒置原则,这时候在根据实现类去写接口,这种是不对的,应该首先设计抽象,然后在根据抽象去实现,应该要面向接口编程。
· 传统的三层架构 · 根据依赖倒置原则来重新设计的三层架构
在传统的三层架构里面,仅仅增加一个接口层,我们就实现了依赖倒置,目的就是降低层与层之间的耦合。有了这样的接口层,三层架构才真正实现了“高内聚、低耦合”的思想。
依赖倒置原则是架构层面上的,那么如何在代码层面上实现呢?下面看控制反转。
3)IOC控制反转
一种反转流、依赖和接口的方式,它把传统上由程序代码直接操控的对象的控制器(创建、维护)交给第三方,通过第三方(IOC容器)来实现对象组件的装配和管理。
1.怎么理解IOC?
明确“谁控制谁,控制什么,为何是反转(有反转应该有正转),哪些方面反转了“
谁控制谁,控制什么:由IOC容器控制对象的创建。谁控制谁?IOC容器控制了对象;控制了什么?主要控制了外部资源获取。
为何是反转,哪些方面反转了︰
正转:传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;
反转:由容器来帮忙创建及注入依赖对象﹔
为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
4)IOC容器
IOC容器,也可以叫依赖注入框架,是由一种依赖注入框架提供的,主要用来映射依赖,管理对象的创建和生存周期。IOC容器本质上就是一个对象,通常会把程序里面所有的类都注册进去,使用这个类的时候,直接从容器里面去解析。
5)DI依赖注入
依赖注入是控制反转的一种实现方式,依赖注入的目的就是为了实现控制反转。
依赖注入是一种工具或手段,目的是帮助我们开发出松耦合、可维护的程序。
详情请转大佬文章:C#编程之依赖倒转原则
6)反射(Reflection)
1.基础
反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。
理论详情 作者另一文章:C#反射
实现反射的相关类:
类 | 操作对象 |
Stytem.Type | 类型 |
System.Reflection.Assembly | 程序集 |
...... | ...... |
基础知识 作者另一文章:C#反射相关基础
2.实验——获取目标程序集中的类,调用其中指定方法
- 框架
- 主项目——控制台
using System.Reflection;
namespace Y_TestProject
{
public class Program
{
static void Main(string[] args)
{
/*--获取本项目的程序集,获取其下指定类,调用指定方法--*/
Assembly a = Assembly.LoadFrom("Y_TestProject.dll");
//“Assembly.Load("Y_TestProject.dll");"报错,系统找不到指定的文件
//Type t0 = a.GetType("AC"); //t为null
Type t1 = a.GetType("Y_TestProject.AC"); //正确
MethodInfo mi1 = t1.GetMethod("ACP");
mi1.Invoke(Activator.CreateInstance(t1), null);
/*--获取导入的dll文件,获取其下指定类,调用指定方法--*/
//Assembly aClassLibrary0 = Assembly.Load("ClassLibrary.dll");//报错,系统找不到指定的文件
Assembly aClassLibrary1 = Assembly.LoadFrom("ClassLibrary.dll"); //正确
Type t3 = aClassLibrary1.GetType("LeiKu.Pub"); //获取类型
MethodInfo mi2= t3.GetMethod("Printf"); //获取方法
mi2.Invoke(Activator.CreateInstance(t3),new object[] { "调用成功" }); //方法调用
Console.ReadLine();
}
}
public class AC
{
public string A;
public void ACP()
{
Console.WriteLine("ACP");
}
}
}
-
引入的程序集代码
namespace LeiKu
{
internal class Pub
{
public void Printf(string msg)
{
Console.BackgroundColor = ConsoleColor.Green; //改控制台背景元素
Console.WriteLine(msg); //打印信息
}
}
}
-
结果