反射reflection使用解读

一、 理论

反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata
IL: 也是一种面向对象语言
metadata元数据:数据清单,描述DLL/exe里面的各种信息,CLR运行时会先看metadata

二、 反射使用

#region 普通用法
{
  IDBHelper iDBHelper = new MySqlHelper();
  iDBHelper.Query();
}
#endregion
#region Reflection用法
{
  //1. 动态加载一个完整的dll/exe名称,不需要后缀,从根目类所在的路径进行查找,同名dll和exe,dll优先
  Assembly assemnly = Assembly.Load("DB.MySql");
  //完整路径
  Assembly assemnly = Assembly.LoadFile(@"D:\reflection\bin\debug\DB.MySql".dll);
  //当前路径
  Assembly assemnly = Assembly.LoadFrom("DB.MySql.dll");
  //获取类型,完整类名称
  Type type = assemnly.GetType("DB.MySql.MySqlHelper");
  object oDbHelper = Activator.CreateInstance(type);
  //有参数的构造函数
  object oDbHelper = Activator.CreateInstance(type,new object[]{ 123 });
  //为什么不能直接Query?实际上是有Query方法的,只是因为编译器不认可
  //oDbHelper.Query();

  //类型转换,不报错,类型不对就返回null
  IDbHelper iDbHelper = oDbHelper as IDbHelper;
  iDbHelper.Query();
  //不做类型转换
  var method  = type.GetMethod("Query");
  method.Invoke(oDbHelper,null);
 //有重载方法?
  var method  = type.GetMethod("Query",new Type[]{ typeof(int),typeof(string) });
  method.Invoke(oDbHelper,new object[]{123,"123"});
  //调用带参数方法
   method.Invoke(oDbHelper,new object[]{123});
  //静态方法可以不传实例
   method.Invoke(null,new object[]{123,"123"});

  //dynamic编译器不检查,运行时才检查
  dynamic dDbHelper = Activator.CreateInstance(type);
  dDbHelper.Query();
 
  //查看全部类和方法
  foreach(var type in assembly.GetTypes()
  {
     console.WriteLine(type.Name);//类名
     foreach(var method in type.GetMethods())
     {
        console.WriteLine(method.Name);//方法
     }
     foreach(var construct in type.GetConstructors())
     {
        console.WriteLine(construct .Name);//构造函数
     }
  }
}
#endregion

三、 使用更复杂了?封装工厂

{
  //Reflector + Factory + Config
  //可配置,如果需要换成SqlServer处理时,可以直接改配置文件
  //实现类必须在目录下面
  //可扩展:完全不修改原有代码,只是增加新的实现,复制dll,修改配置文件,就可以支持新功能
  //反射的动态加载和动态创建对象,以及配置文件结合
  IDbHelper iDbHelper = SimpleFactory.CreateInstance();
  iDbHelper.Query();
}
public class SimpleFactory
{
   private static string IDBHelperConfig = ConfigurationManager.AppSetting["IDBHelperConfig"];

   private static string DllName = IDBHelperConfig.Split(',')[0];
   private static string TypeName = IDBHelperConfig.Split(',')[1];
   public static IDBHelper CreateInstance()
   {
       Assembly assemnly = Assembly.Load(DllName);
       Type type = assemnly.GetType(TypeName );
       object oDbHelper = Activator.CreateInstance(type);
       IDbHelper iDbHelper = oDbHelper as IDbHelper;
       return iDbHelper;
   }
}

四、应用场景

1、MVC:浏览器只告诉了服务器Controller(类型)名称和方法名称
MVC在启动时会先加载--扫描全部的dll--找到全部的Controller--存起来--请求来的时候,用Controller来匹配的
MVC局限性--Action如果重载了,反射是无法区分的----MVC如果重载方法只能通过HttpMethod+特性区分HttpPost/HttpGet
2、AOP

//根据dll名称、类型名称、方法名称就可以调用方法

五、延升,反射调用私有方法,调用泛型方法

{
 //调用私有方法
 Assembly assembly = Assembly.Load("DB.SqlServer");
 Type type = assemnly.GetType("DB.MySql.MySqlHelper");
 object oDbHelper = Activator.CreateInstance(type);
 var method = type.GetMethod("Show4",BindingFlag.Instance | BindingFlag.NonPublic);
 method.Invoke(oDbHelper,null);
}
{
//泛型方法
 Assembly assembly = Assembly.Load("DB.SqlServer");
 Type type = assemnly.GetType("DB.MySql.MySqlHelper");
 object oDbHelper = Activator.CreateInstance(type);
 var method = type.GetMethod("Show");
 method.MakeGenericMethod(new Type[]{typeof(string),typeof(int)});
 method.Invoke(oDbHelper,new object[]{"123",123});
}
{
//泛型类下的泛型方法
 Assembly assembly = Assembly.Load("DB.SqlServer");
 Type type = assemnly.GetType("DB.MySql.MySqlHelper`1").MakeGenericType(typeof(int));
 object oDbHelper = Activator.CreateInstance(type);
 var method = type.GetMethod("Show");
 method.MakeGenericMethod(new Type[]{typeof(string),typeof(int)});
 method.Invoke(oDbHelper,new object[]{"123",123});
}
image.png

六、总结
反射的优缺点:
优点:动态
缺点:1.使用麻烦(封装解决) 2.避开编译器检查 3.性能问题
测试:100万次循环,普通方法 41ms,反射 6512ms
但是换个角度分析下,100次循环,反射耗时0.65ms
反射可以缓存优化,dll加载和类型获取只执行一次,
100万次循环,普通方法 48ms 反射 103ms

MVC--Asp.net--ORM--IOC--AOP都在用反射,几乎都用缓存
MVC&ORM 启动都很慢,完成了很多初始化,反射信息,后面启动就很快

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容

  • 反射 反射是无处不在的,MVC、AOP、IOC、ORM、Attribute等等 dll-IL-metadata-反...
    半吊子先生_123c阅读 191评论 0 0
  • ILSpy: exe dll -> 反编译为源码或IL,逆向工程IL也是面向对象语言metadata(元数据): ...
    coocms阅读 250评论 0 0
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,644评论 18 399
  • 在谈论Reflection之前还是想给大家先看一个图: 逆向工程,可以把Dll/Exe文件反编译回来,IL是对标于...
    浅谈码生活阅读 4,711评论 2 4
  • 推荐指数: 6.0 书籍主旨关键词:特权、焦点、注意力、语言联想、情景联想 观点: 1.统计学现在叫数据分析,社会...
    Jenaral阅读 5,721评论 0 5