什么是反射?
反射反射, 程序员的快乐, 在. Net 领域程序设计中, 反射是无处不在的, MVC,ASP.NET, 各种 ORM,IoC,AOP 几乎所有的框架都离不开反射. 反编译工具使用的底层技术用的不是反射, 是一种逆向工程.
反射 (Reflection,System.Reflection), 是. Net Framework 提供的一个帮助类库, 可以读取并使用 Metadata 中描述的数据信息. 元数据(Metadata), 描述了 dll/exe 里面的各种信息, 又称中介数据, 中继数据, 为描述数据的数据(data about data), 主要是描述数据属性(property) 的信息, 用来支持如指示存储位置, 历史数据, 资源查找, 文件记录等功能.
反射的优缺点:
优点: 动态 - 在不破坏原有程序的情况下, 可对程序进行良好的扩展. Eg: 我们有这样一需求, 项目在最初的时候用的是 MySQL 数据库, 由于项目情况变化需要更换成 SqlServer 数据库. 面对这种项目的需求, 传统的解决方法是在项目中添加新的 SqlServer 数据库访问代码, 将数据库访问实现层更改为 SqlServer, 最后编译源代码并重新发布.
传统解决方法示例伪代码如下:
- IDBHelper iDBHelper = new MySqlHelper();
- IDBHelper iDBHelper = new SqlServerHelper();
- iDBHelper.Query();
使用反射的示例代码:
- namespace ReflectionDemo
- {
- /// <summary>
- /// 反射工厂
- /// </summary>
- public class SimpleFactory
- {
- // 读取配置文件
- private static string IDBHelperConfig = ConfigurationManager.AppSettings["IDBHelperConfig"];
- // 获取需要加载的 dll 名称
- private static string DllName = IDBHelperConfig.Split(',')[0];
- // 获取需要的类型名称
- private static string TypeName = IDBHelperConfig.Split(',')[1];
- /// <summary>
- /// 通过反射动态加载与类型名称相匹配的实例
- /// </summary>
- /// <returns></returns>
- public static IDBHelper CreateInstance()
- {
- Assembly assembly = Assembly.Load(DllName);
- Type type = assembly.GetType(TypeName);
- object oDBHelper = Activator.CreateInstance(type);
- IDBHelper iDBHelper = oDBHelper as IDBHelper;
- return iDBHelper;
- }
- }
- }
- <add key="IDBHelperConfig" value="MySqlDb,MySqlDb.MySqlHelper"/>
- IDBHelper iDBHelper = SimpleFactory.CreateInstance();
- iDBHelper.Query();
通过反射实现了程序的可配置, 通过修改配置文件就可以自动切换实现类, 实现类必须是事先已有的, 没有将实现类固定, 而是通过配置文件执行, 通过反射创建的. 可扩展: 完全不修改原有代码, 只是增加新的实现, 修改配置文件, 就可以支持新功能. 这就是反射的动态特性.
缺点: 使用麻烦, 避开编译器检查导致运程序行时异常变多, 性能问题.
通过反射调用构造函数
- namespace SqlServerDb
- {
- /// <summary>
- /// 反射测试类
- /// </summary>
- public class ReflectionTest
- {
- #region Identity
- /// <summary>
- /// 无参构造函数
- /// </summary>
- public ReflectionTest()
- {
- Console.WriteLine("这里是 {0} 无参数构造函数", this.GetType());
- }
- /// <summary>
- /// 带参数构造函数
- /// </summary>
- /// <param name="name"></param>
- public ReflectionTest(string name)
- {
- Console.WriteLine("这里是{0} 有参数[string] 构造函数", this.GetType());
- }
- public ReflectionTest(int id)
- {
- Console.WriteLine("这里是{0} 有参数[int] 构造函数", this.GetType());
- }
- #endregion
- #region Method
- /// <summary>
- /// 无参方法
- /// </summary>
- public void Show1()
- {
- Console.WriteLine("这里是 {0} 的 Show1", this.GetType());
- }
- /// <summary>
- /// 有参数方法
- /// </summary>
- /// <param name="id"></param>
- public void Show2(int id)
- {
- Console.WriteLine("这里是 {0} 的 Show2", this.GetType());
- }
- /// <summary>
- /// 重载方法之一
- /// </summary>
- /// <param name="id"></param>
- /// <param name="name"></param>
- public void Show3(int id, string name)
- {
- Console.WriteLine("这里是 {0} 的 Show3", this.GetType());
- }
- /// <summary>
- /// 重载方法之二
- /// </summary>
- /// <param name="name"></param>
- /// <param name="id"></param>
- public void Show3(string name, int id)
- {
- Console.WriteLine("这里是 {0} 的 Show3_2", this.GetType());
- }
- /// <summary>
- /// 重载方法之三
- /// </summary>
- /// <param name="id"></param>
- public void Show3(int id)
- {
- Console.WriteLine("这里是 {0} 的 Show3_3", this.GetType());
- }
- /// <summary>
- /// 重载方法之四
- /// </summary>
- /// <param name="name"></param>
- public void Show3(string name)
- {
- Console.WriteLine("这里是 {0} 的 Show3_4", this.GetType());
- }
- /// <summary>
- /// 重载方法之五
- /// </summary>
- public void Show3()
- {
- Console.WriteLine("这里是 {0} 的 Show3_1", this.GetType());
- }
- /// <summary>
- /// 私有方法
- /// </summary>
- /// <param name="name"></param>
- private void Show4(string name)
- {
- Console.WriteLine("这里是 {0} 的 Show4", this.GetType());
- }
- /// <summary>
- /// 静态方法
- /// </summary>
- /// <param name="name"></param>
- public static void Show5(string name)
- {
- Console.WriteLine("这里是 {0} 的 Show5", typeof(ReflectionTest));
- }
- #endregion
- }
- }
- Assembly assembly = Assembly.Load("SqlServerDb");
- Type type = assembly.GetType("SqlServerDb.ReflectionTest");
- foreach (ConstructorInfo ctor in type.GetConstructors())
- {
- Console.WriteLine($"ctor.Name:{ctor.Name}");
- foreach (var parameter in ctor.GetParameters())
- {
- Console.WriteLine($"ParameterType:{parameter.ParameterType},parameterName: {parameter.Name}");
- }
- }
- object oTest1 = Activator.CreateInstance(type);
- object oTest2 = Activator.CreateInstance(type, new object[] { 123 });
- object oTest3 = Activator.CreateInstance(type, new object[] { "陌殇" });
反射破坏单例
- // 反射破坏单例 --- 就是反射调用私有构造函数
- Assembly assembly = Assembly.Load("SqlServerDb");
- Type type = assembly.GetType("SqlServerDb.Singleton");
- Singleton singletonA = (Singleton)Activator.CreateInstance(type, true);
- Singleton singletonB = (Singleton)Activator.CreateInstance(type, true);
- 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);
- }
- }
- }
- Assembly assembly = Assembly.Load("SqlServerDb");
- Type type = assembly.GetType("SqlServerDb.GenericClass`3");
- GenericClass<string, int, DateTime> genericClass = new GenericClass<string, int, DateTime>();
- //genericClass.Show("12", 1, DateTime.Now);
- //object oGeneric = Activator.CreateInstance(type);
- Type typeMake = type.MakeGenericType(new Type[] { typeof(string), typeof(int), typeof(DateTime) });
- object oGeneric = Activator.CreateInstance(typeMake);
反射调用泛型方法
- Assembly assembly = Assembly.Load("SqlServerDb");
- Type type = assembly.GetType("SqlServerDb.GenericMethod");
- object oGeneric = Activator.CreateInstance(type);
如果反射创建对象之后, 知道方法名称, 怎么样不做类型转换, 直接调用方法?
- 2 Assembly assembly = Assembly.Load("SqlServerDb");
- Type type = assembly.GetType("SqlServerDb.ReflectionTest");
- object oTest = Activator.CreateInstance(type);
- foreach (var method in type.GetMethods())
- {
- Console.WriteLine(method.Name);
- foreach (var parameter in method.GetParameters())
- {
- Console.WriteLine($"{parameter.Name} {parameter.ParameterType}");
- }
- }
- {
- ReflectionTest reflection = new ReflectionTest();
- reflection.Show1();
- }
- {
- MethodInfo method = type.GetMethod("Show1");
- //if()
- method.Invoke(oTest, null);
- }
- {
- MethodInfo method = type.GetMethod("Show2");
- method.Invoke(oTest, new object[] { 123 });
- }
- {
- MethodInfo method = type.GetMethod("Show3", new Type[] { });
- method.Invoke(oTest, null);
- }
- {
- MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int) });
- method.Invoke(oTest, new object[] { 123 });
- }
- {
- MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string) });
- method.Invoke(oTest, new object[] { "一生为你" });
- }
- {
- MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(int), typeof(string) });
- method.Invoke(oTest, new object[] { 234, "心欲无痕" });
- }
- {
- MethodInfo method = type.GetMethod("Show3", new Type[] { typeof(string), typeof(int) });
- method.Invoke(oTest, new object[] { "PHS", 345 });
- }
- {
- MethodInfo method = type.GetMethod("Show5");
- method.Invoke(oTest, new object[] { "张中魁" });// 静态方法实例可以要
- }
- {
- MethodInfo method = type.GetMethod("Show5");
- method.Invoke(null, new object[] { "张中魁" });// 静态方法实例也可以不要
- }
反射调用私有方法
- {
- // 调用私有方法
- Console.WriteLine("&&&&&&&&&&&&&&&&&&&& 私有方法 &&&&&&&&&&&&&&&&&&&");
- Assembly assembly = Assembly.Load("SqlServerDb");
- Type type = assembly.GetType("SqlServerDb.ReflectionTest");
- object oTest = Activator.CreateInstance(type);
- var method = type.GetMethod("Show4", BindingFlags.Instance | BindingFlags.NonPublic);
- method.Invoke(oTest, new object[] { "我是老王" });
- }
反射调用泛型方法
- 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 });
反射调用泛型方法加泛型类
- Assembly assembly = Assembly.Load("SqlServerDb");
- // 在获取类型的同时通过 MakeGenericType 指定泛型的参数类型
- Type type = assembly.GetType("SqlServerDb.GenericDouble`1").MakeGenericType(typeof(int));
- object oObject = Activator.CreateInstance(type);
- MethodInfo method = type.GetMethod("Show").MakeGenericMethod(typeof(string), typeof(DateTime));
- method.Invoke(oObject, new object[] { 345, "感谢有梦", DateTime.Now });
来源: https://www.cnblogs.com/netlws/p/11001218.html