反射
反射提供描述程序集、模块和类型的对象(Type 类型)。 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问器字段和属性。 如果代码中使用了特性,可以利用反射来访问它们。
反射的类位于System.Reflection命名空间中,他们是.net Reflection API的一部分,所以在使用的反射的程序中一般都要使用 System.Reflection的命名空间。
System. Type类包装了类型,因此是整个反射子系统的核心,这个类中包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型的信息。
通过反射获取类型信息
internal class Program { static void Main(string[] args) { //获取类型信息 Type t = typeof(int); Console.WriteLine($"命名空间名称:{t.Namespace}"); Console.WriteLine($"基类:{t.BaseType}"); Console.WriteLine($"全名:{t.FullName}"); Console.WriteLine($"是否为抽象类型:{t.IsAbstract}"); Console.WriteLine($"是否为密封类:{t.IsSealed}"); //获取所以公有成员 Type t2 = typeof(TestClass); var mi = t2.GetMembers();//获取所以公有成员 foreach (var m in mi) { //Console.WriteLine($"【{m.MemberType.ToString()} : {m.Name}】"); } //获取方法相关的信息 MethodInfo[] methodList = t.GetMethods(); foreach (var m in methodList) { Console.Write($"方法的返回类型:{m.ReturnType.Name}"); Console.Write($"方法的名称:{m.Name} ("); //获取方法参数列表并保持在ParameterInfo对象数组中 ParameterInfo[] parameters = m.GetParameters(); for (int i = 0; i < parameters.Length; i++) { Console.Write($"方法的参数类型名称{parameters[i].ParameterType.Name}"); Console.Write($"方法的参数名{parameters[i].Name}"); if (i + 1 < parameters.Length) { Console.Write($", "); } } Console.Write($")"); Console.WriteLine(); } Console.ReadLine(); } } class TestClass { public string TestName { get; set; } public int Sum(int x, int y) { return x + y; } }
通过反射调用构造函数和方法
internal class Program { static void Main(string[] args) { #region 使用反射调用程序集中类型中的方法 //加载dll Assembly assembly = Assembly.Load("DemoLibrary"); //获取类型信息 Type type = assembly.GetType("DemoLibrary.DemoClass"); object demoClass = Activator.CreateInstance(type); //创建对象 DemoClass demo = (DemoClass)demoClass; //类型转换 demo.Show(); //方法调用 #endregion #region 调用不同参数的构造函数 Type type2 = assembly.GetType("DemoLibrary.DemoClass2"); object demoClass2 = Activator.CreateInstance(type2); object demoClass22 = Activator.CreateInstance(type2,new object[] { 123}); object demoClass222 = Activator.CreateInstance(type2,new object[] { "abc"}); #endregion #region 调用泛型 // `占位符;2表示参数个数(一个的时候也要写) Type type3 = assembly.GetType("DemoLibrary.Demo3`2"); //object demo3 = Activator.CreateInstance(type3); //这么写报错,因为没有指定类型 //指定泛型的参数类型 Type newType = type3.MakeGenericType(new Type[] { typeof(int), typeof(string) }); object objNewType = Activator.CreateInstance(newType); #endregion Console.ReadKey(); } }
程序集中的类:
DemoClass:
public class DemoClass { public DemoClass() { Console.WriteLine($"{this.GetType().Name} 被构造"); } public void Show() { Console.WriteLine($"{this.GetType().Name}.Show"); } }
DemoClass2:
public class DemoClass2 { /// <summary> /// 无参数构造函数 /// </summary> public DemoClass2() { Console.WriteLine($"这是无参数{this.GetType().Name} 构造函数"); } /// <summary> /// 带参数的构造函数 /// </summary> public DemoClass2(string strVal) { Console.WriteLine($"这有参数{this.GetType().Name} 构造函数,传入的值:{strVal}"); } /// <summary> /// 带参数的构造函数 /// </summary> public DemoClass2(int intVal) { Console.WriteLine($"这有参数{this.GetType().Name} 构造函数,传入的值:{intVal}"); } }
Demo3:
public class Demo3<T, X> { public void Show(T t, X x) { Console.WriteLine($"t.type={t.GetType()},x.type={x.GetType()}"); } }