依赖倒置、反射、泛型、委托、AOP
1.什么是依赖倒置(DIP):是高层模块负责定义接口,底层模块负责实现。抽象不应该依赖于实现,实现应该依赖于抽象。抽象是个高层模块,定义好抽象,就可以对实现进行不同的实现。Human是高层模块Man的抽象,Car是底层模块Audi的抽象.不难发现高层的Man并不直接依赖底层的Audi,其两者都有各自的抽象,这就是上文提到的”高层不应该直接依赖底层,双方应该依赖抽象”
DIP是设计原则(如何依赖),控制反转IOC是设计模式(怎么做),用来实现对象之间的“解耦”,ioc有依赖注入和服务定位2种,依赖注入di,构造函数注入、属性注入、接口注入。
public
class
AccessDal:IDataAccess
{
public
void
Add()
{
Console.WriteLine(
"在ACCESS数据库中添加一条记录!"
);
}
}
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
namespace
DIPTest
{
class
Program
{
static
void
Main(
string
[] args)
{
AccessDal dal =
new
AccessDal();
//在外部创建依赖对象
Order order =
new
Order(dal);
//通过构造函数注入依赖
order.Add();
Console.Read();
}
}
}
除了手动注入还有ioc容器的方式。
Ninject、Castle Windsor、Autofac、StructureMap、Unity、MEF、Spring.NET、LightInject
从原来的对象相互依赖,通过第三方将各个对象解耦。这个第三方就是IOC容器,起到粘合剂的作用。
由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
IOC中最基本的技术就是“反射(Reflection)”编程
容器使用的基本套路是不变的,实例化容器,然后注册,然后使用即可。
IUnityContainer unityContainer = new UnityContainer();//实例化控制器
//实现注入
unityContainer.RegisterType<IBird, Swallow>();//IBird一个鸟类的接口,定义鸟叫的方法。//swallow对鸟类实例化,
IBird bird = unityContainer.Resolve<IBird>();
bird.Say();
接口代码:
public interface IBird
{
void Say( );
实例化代码:
-
public class Swallow : IBird
-
{
-
public void Say( )
-
{
-
Console.WriteLine("燕子在叫...");
-
}
实现燕子在叫。
实例化另一个对象:
public class Sparrow : IBird
{ public void Say()
{ Console.WriteLine("麻雀在叫....");
}}
实现输出:
//实例化一个控制器
IUnityContainer unityContainer = new UnityContainer();
//实现注入
unityContainer.RegisterType<IBird, Swallow>();
unityContainer.RegisterType<IBird, Sparrow>();
IBird bird = unityContainer.Resolve<IBird>();
bird.Say();
Console.Read();
出现最后一个注入的实现。麻雀在叫...
//实例化一个控制器
IUnityContainer unityContainer = new UnityContainer();
//实现注入,用别名区分实现
unityContainer.RegisterType<IBird, Swallow>("Swallow");
unityContainer.RegisterType<IBird, Sparrow>("Sparrow");
IBird swallow = unityContainer.Resolve<IBird>("Swallow");
IBird sparrow = unityContainer.Resolve<IBird>("Sparrow");
swallow.Say();
sparrow.Say();
通过加上别名实现2种实例。
2.反射就是动态获取动态获得程序集里面的元数据,如类中的属性和方法。
程序集是啥,理解是引用的dll是程序集,早绑定就是引用程序集,然后new对象,运行时之前就加载他,进一步获取属性方法等;晚绑定即反射,先加载需要反射的dll
Assembly assembly = Assembly.Load("Ruanmou.DB.Sqlserver");//1 动态加载 默认加载当前路径的dll文件,不需要后缀
//Assembly assembly1 = Assembly.LoadFile(@"E:\online7\20160928Advanced7Course2Reflection\MyReflection\MyReflection\bin\Debug\Ruanmou.DB.Sqlserver.dll");// 必须是完整路径
//Assembly assembly2 = Assembly.LoadFrom("Ruanmou.DB.Sqlserver.dll");// 可以是当前路径 也可以是完整路径
Assembly asmb = Assembly.LoadFrom(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "xxx.dll"));
反射获取dll下的类:
foreach (var item in assembly.GetTypes())
{
Console.WriteLine(item.FullName);
}
获取方法:
foreach (varitem in typeDBHelper.GetMethods())
{
Console.WriteLine(item.Name);
}
GetProperties()获取属性,GetFields()获取字段
SYSTEM.Type返回加载堆上的类型对象,Getmethod获取某个方法,invoke执行方法。
//通过程序集的名称反射
Assembly ass = Assembly.Load("ClassLibrary");
Type t = ass.GetType("ClassLibrary.NewClass");
object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");
MethodInfo mi = t.GetMethod("show");
mi.Invoke(o, null);
如:
Type t= Assembly.Load(config[x]).GetType(config[0]);
cached = Activator.CreateInstance(t) as ICache;
return cached;
3.泛型是啥,是个占位符,将不同类型用一个占位符表示。声明一个可以给多个类型参数共同使用的方法
//声明一个泛型方法 public void GenericMethod<T>(T tParamter) { }
//声明一个泛型接口
public interface IGenericInterface<T>
{
}
//声明一个泛型类
public class IGenericClass<T>
{
}
//声明一个泛型委托
public delegate void GenericDelegate<T>(T tParameter);
public delegate void GenericDelegate<T>();
泛型约束:
是对T的约束,基类约束、接口约束(IInterface)、引用类型约束(where T : class )、值类型(where T : struct)、无参构造函数约束(where T : new())
where T : new()只要T是否有无参构造函数,如: Tester<SomeType> t = new Tester<SomeType>(); 判断SomeType是否有无参构造函数。
协变和逆变:使用in T作为参数,只能作为传入参不能作为返回值,父类传给子类,这是逆变。使用out T作为参数,只能作为return 的值,不能作为传入值,协变。
public interface ICustomerListIn<in T> { void Show(T t); }
public class CustomerListIn<T> : ICustomerListIn<T> { public void Show(T t) { } }逆变
public interface ICustomerListOut<out T> { T Get(); }
public class CustomerListOut<T> : ICustomerListOut<T> { public T Get() { return default(T); } }协变
4. 委托:
委托都会提到事件,事件是委托的一个特例,委托是把方法作为参数,在另一个方法里面传递和调用。
//step01:首先用delegate定义一个委托 。 public delegate int CalculatorAdd(int x, int y);
// step02:声明一个方法来对应委托。 public int Add(int x, int y) { return x + y; }
//step03:用这个方法来实例化这个委托。 CalculatorAdd cAdd = new CalculatorAdd(Add); //int result = cAdd(5, 6); int result = cAdd.Invoke(5,6);
匿名方法:
public delegate int CalculatorAdd(int x, int y);
CalculatorAdd cAdd = delegate(int x, int y) { return x + y; }; int result = cAdd.Invoke(5, 6);
lambda:简化匿名方法
public delegate int CalculatorAdd(int x, int y);
//方法一: CalculatorAdd cAdd1 = (int x, int y) => { return x + y; }; int result1 = cAdd1(5, 6); //方法二: CalculatorAdd cAdd2 = (x, y) => { return x + y; }; int result2 = cAdd2(5, 6); //方法三: CalculatorAdd cAdd3 = (x, y) => x + y; int result3 = cAdd3(5, 6);
泛型委托:一步是定义一个委托,另一步是用一个方法来实例化一个委托,用Func来简化一个委托的定义
//方法三: Func<int, int, int> cAdd3 = (x, y) => x + y; int result3 = cAdd3(5, 6);
Action是无返回值的泛型委托; Func是有返回值的泛型委托; predicate 是返回bool型的泛型委托 ;Comparison 表示比较同一类型的两个对象的方法:public delegate int Comparison<T>(T x, T y);
委托的使用:先创建一个实例 public delegat int dint(int x,int y),定义方法 public int add(int x,int y),定义委托变量 delegate d1,关联方法 d1=add 关联多个方法d1+=add,调用委托实例d1(1,3)
5.AOP
AOP:面向切面编程,统一处理业务逻辑的一种技术。场景:日志记录,错误捕获、性能监控等。通过代理对象来间接执行真实对象,同装饰类
实现方式:动态代理和IL 编织,静态织入以Postshop为代表,而动态代理分为普通反射、Emit反射、微软提供的.Net Remoting和RealProxy。