什么是反射?

反射反射,程序员的快乐,在.Net领域程序设计中,反射是无处不在的,MVC、ASP.Net、各种ORM、IOC、AOP
几乎所有的框架都离不开反射。反编译工具使用的底层技术用的不是反射,是一种逆向工程。

反射(Reflection、System.Reflection),是.Net Framework提供的一个帮助类库,可以读取并使用Metadata
中描述的数据信息。元数据(Metadata),描述了dll/exe里面的各种信息,又称中介数据、中继数据,为描述数据
<https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE/5947370>的数据(data about data
),主要是描述数据属性 <https://baike.baidu.com/item/%E5%B1%9E%E6%80%A7/1405051>(property)的
信息 <https://baike.baidu.com/item/%E4%BF%A1%E6%81%AF/111163>,用来支持如指示存储位置、历史
<https://baike.baidu.com/item/%E5%8E%86%E5%8F%B2/360>数据、资源
<https://baike.baidu.com/item/%E8%B5%84%E6%BA%90/9089683>查找、文件记录等功能。

反射的优缺点:

优点:动态—在不破坏原有程序的情况下,可对程序进行良好的扩展。Eg:我们有这样一需求,项目在最初的时候用的是Mysql数据库,由于项目情况变化需要更换成
SqlServer数据库。面对这种项目的需求,传统的解决方法是在项目中添加新的SqlServer数据库访问代码,将数据库访问实现层更改为SqlServer
,最后编译源代码并重新发布。

传统解决方法示例伪代码如下:
1 IDBHelper iDBHelper = new MySqlHelper(); 2 IDBHelper iDBHelper = new
SqlServerHelper();3 iDBHelper.Query();
使用反射的示例代码:
1 namespace ReflectionDemo 2 { 3 /// <summary> 4 /// 反射工厂 5 /// </summary>
6 public class SimpleFactory 7 { 8 //读取配置文件 9 private static string
IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"]; 10 //
获取需要加载的dll名称 11 private static string DllName = IDBHelperConfig.Split(',')[0];
12 //获取需要的类型名称 13 private static string TypeName = IDBHelperConfig.Split(',')[1
];14 /// <summary> 15 /// 通过反射动态加载与类型名称相匹配的实例 16 /// </summary> 17 ///
<returns></returns> 18 public static IDBHelper CreateInstance() 19 { 20
Assembly assembly = Assembly.Load(DllName); 21 Type type =
assembly.GetType(TypeName);22 object oDBHelper = Activator.CreateInstance(type);
23 IDBHelper iDBHelper = oDBHelper as IDBHelper; 24 return iDBHelper; 25 } 26
}27 } <add key="IDBHelperConfig" value="MySqlDb,MySqlDb.MySqlHelper"/>
IDBHelper iDBHelper = SimpleFactory.CreateInstance(); iDBHelper.Query();
通过反射实现了程序的可配置,通过修改配置文件就可以自动切换实现类,实现类必须是事先已有的, 没有将实现类固定,而是通过配置文件执行,通过反射创建的。可扩展:
完全不修改原有代码,只是增加新的实现、修改配置文件,就可以支持新功能。这就是反射的动态特性。

缺点:使用麻烦、避开编译器检查导致运程序行时异常变多、性能问题。

通过反射调用构造函数
1 namespace SqlServerDb 2 { 3 4 /// <summary> 5 /// 反射测试类 6 ///
</summary> 7 public class ReflectionTest 8 { 9 #region Identity 10 ///
<summary> 11 /// 无参构造函数 12 /// </summary> 13 public ReflectionTest() 14 {
15 Console.WriteLine("这里是{0}无参数构造函数", this.GetType()); 16 } 17 18 ///
<summary> 19 /// 带参数构造函数 20 /// </summary> 21 /// <param name="name"></param>
22 public ReflectionTest(string name) 23 { 24 Console.WriteLine("这里是{0}
有参数【string】构造函数", this.GetType()); 25 } 26 27 public ReflectionTest(int id)
28 { 29 Console.WriteLine("这里是{0} 有参数【int】构造函数", this.GetType()); 30 } 31
#endregion 32 33 #region Method 34 /// <summary> 35 /// 无参方法 36 ///
</summary> 37 public void Show1() 38 { 39 Console.WriteLine("这里是{0}的Show1",
this.GetType()); 40 } 41 /// <summary> 42 /// 有参数方法 43 /// </summary> 44
/// <param name="id"></param> 45 public void Show2(int id) 46 { 47 48
Console.WriteLine("这里是{0}的Show2", this.GetType()); 49 } 50 /// <summary> 51
/// 重载方法之一 52 /// </summary> 53 /// <param name="id"></param> 54 /// <param
name="name"></param> 55 public void Show3(int id, string name) 56 { 57
Console.WriteLine("这里是{0}的Show3", this.GetType()); 58 } 59 /// <summary> 60
/// 重载方法之二 61 /// </summary> 62 /// <param name="name"></param> 63 ///
<param name="id"></param> 64 public void Show3(string name, int id) 65 { 66
Console.WriteLine("这里是{0}的Show3_2", this.GetType()); 67 } 68 /// <summary>
69 /// 重载方法之三 70 /// </summary> 71 /// <param name="id"></param> 72 public
void Show3(int id) 73 { 74 Console.WriteLine("这里是{0}的Show3_3", this
.GetType()); 75 } 76 /// <summary> 77 /// 重载方法之四 78 /// </summary> 79 ///
<param name="name"></param> 80 public void Show3(string name) 81 { 82
Console.WriteLine("这里是{0}的Show3_4", this.GetType()); 83 } 84 85 ///
<summary> 86 /// 重载方法之五 87 /// </summary> 88 public void Show3() 89 { 90
Console.WriteLine("这里是{0}的Show3_1", this.GetType()); 91 } 92 93 ///
<summary> 94 /// 私有方法 95 /// </summary> 96 /// <param name="name"></param>
97 private void Show4(string name) 98 { 99 Console.WriteLine("这里是{0}的Show4",
this.GetType()); 100 } 101 102 /// <summary> 103 /// 静态方法 104 /// </summary>
105 /// <param name="name"></param> 106 public static void Show5(string name)
107 { 108 Console.WriteLine("这里是{0}的Show5", typeof(ReflectionTest)); 109 } 110
#endregion 111 } 112 } 1 Assembly assembly = Assembly.Load("SqlServerDb"); 2
Type type = assembly.GetType("SqlServerDb.ReflectionTest"); 3 foreach
(ConstructorInfo ctorin type.GetConstructors()) 4 { 5 Console.WriteLine($"
ctor.Name:{ctor.Name}"); 6 foreach (var parameter in ctor.GetParameters()) 7
{ 8 Console.WriteLine($"ParameterType:{parameter.ParameterType},parameterName:
{parameter.Name}"); 9 } 10 } 11 object oTest1 =
Activator.CreateInstance(type);12 object oTest2 = Activator.CreateInstance(type,
new object[] { 123 }); 13 object oTest3 = Activator.CreateInstance(type, new
object[] { "陌殇" });
 反射破坏单例
1 //反射破坏单例---就是反射调用私有构造函数 2 Assembly assembly = Assembly.Load("SqlServerDb"); 3
Type type = assembly.GetType("SqlServerDb.Singleton"); 4 Singleton singletonA
= (Singleton)Activator.CreateInstance(type,true); 5 Singleton singletonB =
(Singleton)Activator.CreateInstance(type,true); 6 Console.WriteLine($"
{object.ReferenceEquals(singletonA, singletonB)}");
反射调用泛型类
namespace SqlServerDb { /// <summary> /// 泛型测试类 /// </summary> /// <typeparam
name="T"></typeparam> /// <typeparam name="W"></typeparam> /// <typeparam
name="X"></typeparam> public class GenericClass<T, W, X> { public
GenericClass() { Console.WriteLine("GenericClass<T, W, X>的构造函数被调用了"); } public
void Show(T t, W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}"
, t.GetType().Name, w.GetType().Name, x.GetType().Name); } }/// <summary> ///
泛型测试方法/// </summary> public class GenericMethod { public GenericMethod() {
Console.WriteLine("GenericMethod类的构造函数被调用了。"); } public void Show<T, W, X>(T t,
W w, X x) { Console.WriteLine("t.type={0},w.type={1},x.type={2}",
t.GetType().Name, w.GetType().Name, x.GetType().Name); } }public class
GenericDouble<T> { public void Show<W, X>(T t, W w, X x) { Console.WriteLine("
t.type={0},w.type={1},x.type={2}", t.GetType().Name, w.GetType().Name,
x.GetType().Name); } } } 1 Assembly assembly = Assembly.Load("SqlServerDb"); 2
Type type = assembly.GetType("SqlServerDb.GenericClass`3"); 3 GenericClass<
string, int, DateTime> genericClass = new GenericClass<string, int, DateTime>();
4 //genericClass.Show("12", 1, DateTime.Now); 5 //object oGeneric =
Activator.CreateInstance(type); 6 Type typeMake = type.MakeGenericType(new
Type[] {typeof(string), typeof(int), typeof(DateTime) }); 7 object oGeneric =
Activator.CreateInstance(typeMake);
反射调用泛型方法
Assembly assembly = Assembly.Load("SqlServerDb"); Type type =
assembly.GetType("SqlServerDb.GenericMethod"); object oGeneric =
Activator.CreateInstance(type);
如果反射创建对象之后,知道方法名称,怎么样不做类型转换,直接调用方法?
1 2 Assembly assembly = Assembly.Load("SqlServerDb"); 3 Type type =
assembly.GetType("SqlServerDb.ReflectionTest"); 4 object oTest =
Activator.CreateInstance(type); 5 foreach (var method in type.GetMethods()) 6
{ 7 Console.WriteLine(method.Name); 8 foreach (var parameter in
method.GetParameters()) 9 { 10 Console.WriteLine($"{parameter.Name}
{parameter.ParameterType}"); 11 } 12 } 13 { 14 ReflectionTest reflection =
new ReflectionTest(); 15 reflection.Show1(); 16 } 17 { 18 MethodInfo method
= type.GetMethod("Show1"); 19 //if() 20 method.Invoke(oTest, null); 21 } 22 {
23 MethodInfo method = type.GetMethod("Show2"); 24 method.Invoke(oTest, new
object[] { 123 }); 25 } 26 { 27 MethodInfo method = type.GetMethod("Show3",
new Type[] { }); 28 method.Invoke(oTest, null); 29 } 30 { 31 MethodInfo
method = type.GetMethod("Show3", new Type[] { typeof(int) }); 32
method.Invoke(oTest,new object[] { 123 }); 33 } 34 { 35 MethodInfo method =
type.GetMethod("Show3", new Type[] { typeof(string) }); 36 method.Invoke(oTest,
new object[] { "一生为你" }); 37 } 38 { 39 MethodInfo method = type.GetMethod("
Show3", new Type[] { typeof(int), typeof(string) }); 40 method.Invoke(oTest, new
object[] { 234, "心欲无痕" }); 41 } 42 { 43 MethodInfo method = type.GetMethod("
Show3", new Type[] { typeof(string), typeof(int) }); 44 method.Invoke(oTest, new
object[] { "PHS", 345 }); 45 } 46 { 47 MethodInfo method = type.GetMethod("
Show5"); 48 method.Invoke(oTest, new object[] { "张中魁" });//静态方法实例可以要 49 } 50 {
51 MethodInfo method = type.GetMethod("Show5"); 52 method.Invoke(null, new
object[] { "张中魁" });//静态方法实例也可以不要 53 }
反射调用私有方法
1 { 2 //调用私有方法 3 Console.WriteLine("
&&&&&&&&&&&&&&&&&&&&私有方法&&&&&&&&&&&&&&&&&&&"); 4 Assembly assembly =
Assembly.Load("SqlServerDb"); 5 Type type = assembly.GetType("
SqlServerDb.ReflectionTest"); 6 object oTest = Activator.CreateInstance(type); 7
var method = type.GetMethod("Show4", BindingFlags.Instance |
BindingFlags.NonPublic);8 method.Invoke(oTest, new object[] { "我是老王" }); 9 }
反射调用泛型方法
Assembly assembly = Assembly.Load("SqlServerDb"); Type type =
assembly.GetType("SqlServerDb.GenericMethod"); object oGeneric =
Activator.CreateInstance(type);foreach (var item in type.GetMethods()) {
Console.WriteLine(item.Name); } MethodInfo method= type.GetMethod("Show"); //
指定泛型方法的参数类型 var methodNew = method.MakeGenericMethod(new Type[] { typeof(int),
typeof(string), typeof(DateTime) }); object oReturn = methodNew.Invoke(oGeneric,
new object[] { 123, "董小姐", DateTime.Now });
反射调用泛型方法加泛型类
1 Assembly assembly = Assembly.Load("SqlServerDb"); 2 //
在获取类型的同时通过MakeGenericType指定泛型的参数类型 3 Type type = assembly.GetType("
SqlServerDb.GenericDouble`1").MakeGenericType(typeof(int)); 4 object oObject =
Activator.CreateInstance(type);5 MethodInfo method = type.GetMethod("Show"
).MakeGenericMethod(typeof(string), typeof(DateTime)); 6 method.Invoke(oObject,
new object[] { 345, "感谢有梦", DateTime.Now });
 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信