泛型+反射

泛型

object : 1、任何父类出现的地方,都可以用子类来代替;2、object是一切类型的父类。3、装箱(值从栈复制到堆里)拆箱(堆复制到栈里),性能问题,安全问题

2.0才出现的泛型 T  泛型方法: 声明的时候可以不指定类型,使用的时候指定类型;

泛型在编译器编译时不确定类型,占位符表达;机器码的时候类型已确定,在CLR用指定的类型把占位符替换掉了。

泛型缓存

缓存:把数据存起来,下次直接用上次的结果。

静态字段缓存,静态属性常驻内存。

Webservice   wcf  不支持泛型:服务在发布的时候 参数类型需要确认好.

泛型方法 public  void  A<T>(T t) {}: 为了一个方法满足不同的类型的需求

泛型类 public class A<T>  List<T>{} :  为了一个类满足不同类型的需求

public class AChild<T1,T2>: A<T1>,B<T2>{}

泛型接口 public  interface A<T> {}: 一个接口满足不同类型的需求

泛型委托 public delegate void A<T> {}: 一个委托满足不同类型的需求

泛型约束

public  void A (T t){}  没有约束,任何参数都能传递进来,不安全。

基类约束:public void A (T t) : where T:BaseModel{}:可以把T当作基类--权利;传入的参数必须是BaseModel或者其子类。

接口约束

引用类型约束  public T GetT<T>() where T:class{}

值类型约束 public T GetT<T>() where T:struct{}

无参数构造函数约束 public T GetT<T>() where T:new(){}

用泛型类型参数约束  

public  static  void showTS<T,S>(T  t,S s) where T:People  where  S:T{}

密封类不行,密封类没有子类

约束可以叠加  public void A (T t) : where T:BaseModel1,I1,I2,new(){}

协变、逆变 :泛型接口 泛型委托

协变:让右边可以用子类,让泛型用起来更方便  

例如:   IEnumerable<T> t = new List<S>();  S是T的子类

out修饰  只能作为返回值,不能作为参数

逆变:让右边可以用父类

in 修饰  只能作为参数,不能作为返回值

反射

IL:也是一种面向对象的语言,但是不太好阅读

metadata元数据:数据清单,描述了dll/exe里面的各种信息

反射Reflection:System.Reflection,是.Net Framework 提供的一个帮助类库,可以读取并使用metadata元数据

1、动态加载 一个完整dll名称 不需要后缀 从exe所在的路径进行查找

Assembly  assembly = Assembly.Load(“dll名称”);

Assembly  assembly = Assembly.Load(“dll文件所在的完整路径 并且包括后缀”);

Assembly  assembly = Assembly.LoadFrom(“dll名称.后缀” 或者 “dll文件所在的完整路径 并且包括后缀”);

  1. 获取类型  assembly.GetType(“完整类型名称”)

泛型类  assembly.GetType(“完整类型名称^1”)  添加占位符

3、创建对象  object  oDBHelper = Activator.CreateInstance(type);  //到此步 不能直接调用对象中的方法(因为编译器不允许);类型强制转换之后才能被调用

IDBHelper  oDBHelper =  oDBHelper as  IDBHelper; //as 关键词转换不报错,类型不对转换结果为null

动态类型 dynamic 可以直接调用(动态类型编译器不检查,运行时才检查):  

dynamic  oDBHelper = Activator.CreateInstance(type);  

程序可配置:通过修改配置文件就可以自动切换,不需要重新改代码 编译 发布

程序可扩展:完全不修改原有代码,只是增加新的实现。Copy,修改配置文件,就可以支持新功能。

反射的动态加载和动态创建对象 以及配置文件结合

反射的优势:动态

反射的缺点:调用繁琐、避开了编译器检查、性能问题(反射耗时稍微高一丢丢,大量循环会影响性能;进行缓存优化后,把dll加载和类型获取只执行一次,反射影响就变的更小了)。

单例模式:就是一个类,能保证在整个进程中只有一个实例。

如果反射创建对象之后,知道方法名称,怎么样不做类型转换 直接调用对象中的方法?

1、普通方法

MethodInfo methodInfo  = type.getMethod(“方法名”);

methodInfo.Invoke(对象oDBHelper ,方法参数);  

2、重载方法(方法名一样,方法参数类型或者个数不同):

MethodInfo methodInfo  = type.getMethod(“方法名”,new Type[]{ typeof(int) }); //找方法的时候将方法参数按照顺序将类型传入

methodInfo.Invoke(对象oDBHelper ,new object[]{123});  

3、静态方法对象实例可以要也可以不要:

MethodInfo methodInfo  = type.getMethod(“方法名”);

methodInfo.Invoke(null ,方法参数);

4、私有方法:

MethodInfo methodInfo  =

type.getMethod(“方法名”,BindingFlags.Instance|BindingFlags.NonPublic);

5、泛型方法:

MethodInfo methodInfo  = type.getMethod(“方法名”);

//设置泛型类型,得到全新的方法

var method  = methodInfo.MakeGenericMethod(new Type[]{typeof(int)})

method .Invoke(对象oDBHelper ,方法参数);  

6、泛型类 + 泛型方法

Assembly  assembly = Assembly.Load(“dll名称”);

Type  type = assembly.GetType(“完整类型名称^1”).MakeGenericMethod(new Type[]{typeof(int)});

Object  oObject =  Activator.CreateInstance(type);  

MethodInfo methodInfo  =  type.getMethod(“方法名”).MakeGenericMethod(new Type[]{typeof(string)});

methodInfo.Invoke(oObject ,new object[]{1,”2”});  

dll名称--类型名称--方法名称 目前就能调用方法

MVC就是应用的此方法,调用Action,MVC在启动时会先加载,扫描全部的dll,找到全部的Controller存起来,等请求来之后用Controller来匹配dll

MVC局限性--Action重载--反射是无法区分的--只能通过http get post 请求方式区分

AOP--反射调用方法可以在前后进行其他操作

通过反射动态 生成sql语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值