のDIP(依赖倒置原则)
简单说就是上层模块不应该依赖于下层模块,二者应该通过抽象去依赖。
上层就是指调用者,下层就是者被调用方。
#依赖
创建一个控制台程序,创建两个类Fashi,Sheshou(类有一个属性和方法)
public class Fashi { public string name { get; set; } public Fashi(string _name) { name = _name; } public void Action() { Console.WriteLine("*********************************************"); Console.WriteLine(this.GetType()+":" +this.name + "在中路施法"); Console.WriteLine("*********************************************"); } }
public class Sheshou { public string name { get; set; } public Sheshou(string _name) { name = _name; } public void Action() { Console.WriteLine("*********************************************"); Console.WriteLine(this.GetType()+":"+this.name+"在下路输出"); Console.WriteLine("*********************************************"); } }
常规调用是创建一个类的实例对象,再通过实例对调用方法。这里Program类就是依赖于Fashi和Sheshou类
class
Program
{
static void Main(string[] args)
{
{
static void Main(string[] args)
{
Fashi MZ =
new Fashi("墨子");
Sheshou LB = new Sheshou("鲁班");
MZ.Action();
LB.Action();
Sheshou LB = new Sheshou("鲁班");
MZ.Action();
LB.Action();
Console.ReadKey();
}
}
}
}
#接口
对上面进行改造,创建一个接口IRole(只有一个Action方法),Fashi和Sheshou继承并实现这个接口
interface IRole { void Action(); }
public class Fashi:IRole { public string name { get; set; } public Fashi(string _name) { name = _name; } public void Action() { Console.WriteLine("*********************************************"); Console.WriteLine(this.GetType()+":" +this.name + "在中路施法"); Console.WriteLine("*********************************************"); } }
class Program { static void Main(string[] args) { IRole MZ = new Fashi("墨子"); IRole LB = new Sheshou("鲁班"); MZ.Action(); LB.Action(); Console.ReadKey(); } }
#简单工厂
上面在实例化的时候左边被替换成了IRole接口但是右边仍然是具体的类。我们再来升级改造一下,
配置文件配置相关的信息,通过key可以找到对应的Dll和类
[App.config]
<configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <appSettings> <add key="Fashi" value="IOC,IOC.Fashi"/> <add key="Sheshou" value="IOC,IOC.Sheshou"/> </appSettings> </configuration>
创建一个工厂类,创建实例的工作由工厂去做,这里通过读取配置文件+反射实现。我们只需要传入一个key以及创建实例的构造函数的参数(可选参数)
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace IOC { public static class SimpleFactory { public static string DllName; public static string TypeName; public static T CreateInstance<T>(string key,string name=null) { DllName = ConfigurationManager.AppSettings[key].Split(',')[0]; TypeName = ConfigurationManager.AppSettings[key].Split(',')[1]; Assembly assembly= Assembly.Load(DllName); Type type=assembly.GetType(TypeName); object obj= Activator.CreateInstance(type,name); return (T)obj; } } }
控制台调用。可理解为当遇到实现IRole接口的类时,工厂会根据你提供的key和参数去创建对象实例
class Program { static void Main(string[] args) { IRole ZJ = SimpleFactory.CreateInstance<IRole>("Fashi", "甄姬"); IRole HY = SimpleFactory.CreateInstance<IRole>("Sheshou", "后羿"); ZJ.Action(); HY.Action(); Console.ReadKey(); } }