C#之反射

    xiaoxiao2021-03-25  120

    最近在看反射就把获取各种常用类型变量的方法总结了一遍。C#编译时会把类的信息,变量,特性等都注册在一张表上,而基于System.Reflection下的Assembly,Type类等都可以获取这个表的内容。从而达到根据字符串获取一个类的实例,方法,变量,委托,事件等,以上行为即是我理解的C#的反射过程。代码如下:

    一个随意定义的待测试类和通过反射获取各种类型变量的逻辑。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace sgs { class Class1 { private int num1 = 10; //私有变量 public int num2 = 20; //公有变量 public static int num3 = 30; //公有静态变量 private Class2 c2; //私有实例变量 public delegate int Fool(string para); public event Fool FoolEvent; public Class1() { c2 = new Class2(); } public int Num1 { get { return num1; } set { this.num1 = value; } } private void PrivatePrint() { Console.WriteLine("private print: {0}", num1); EventInfo e; } public int PublicPrint() { Console.WriteLine("public print: {0}", num2); return num1; } public int FoolMethod(string str) { return 100; } } class Class2 { } } using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; using System.Threading; using sgs; namespace ConsoleApplication4 { class Program { static void Main(string[] args) { object result = InvokePublicMethod("sgs.Class1", "PublicPrint", null); Console.WriteLine("reflect public method result : {0}", result.ToString()); object propertyResult = GetProperty("sgs.Class1", "Num1"); Console.WriteLine("reflect property result : {0}", propertyResult.ToString()); object variableResult = GetPublicVariable("sgs.Class1", "num3"); Console.WriteLine("reflect public or static variable : {0}", variableResult); variableResult = GetPrivateVariable("sgs.Class1", "c2"); Console.WriteLine("reflect private or instance variable : {0}", variableResult); object class1 = GetClassInstance("sgs.Class1"); Console.WriteLine("reflect class instance : {0}", class1); object delegateResult = GetDelegate("sgs.Class1", "Fool", "FoolMethod", "sgs"); Console.WriteLine("reflect delete result : {0}", delegateResult); object eventResult = GetEvent("sgs.Class1", "FoolEvent", "sgs"); } // 获取公有方法 private static object InvokePublicMethod(string classFullName, string methodName, params object[] paras) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); MethodInfo methodInfo = type.GetMethod(methodName); return methodInfo.Invoke(obj, paras); } // 获取字段属性 private static object GetProperty(string classFullName, string propertyName) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); PropertyInfo propertyInfo = type.GetProperty(propertyName); return propertyInfo.GetValue(obj); } // 获取公有变量或静态变量 private static object GetPublicVariable(string classFullName, string variableName) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); FieldInfo variableInfo = type.GetField(variableName, BindingFlags.Public | BindingFlags.Static); return variableInfo.GetValue(obj); } // 获取私有变量或实例变量 private static object GetPrivateVariable(string classFullName, string variableName) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); FieldInfo variableInfo = type.GetField(variableName, BindingFlags.Instance | BindingFlags.NonPublic); return variableInfo.GetValue(obj); } // 获取类实例 private static object GetClassInstance(string classFullName) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); return obj; } //获取委托,委托类型在编译后作为类的嵌套类型,所以调用GetNestedType方法 private static object GetDelegate(string classFullName, string delegateName, string methodName, params object[] paras) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); Type delegateInfo = type.GetNestedType(delegateName); MethodInfo methodInfo = type.GetMethod(methodName); //注意调用CreateDelegate方法时若方法是实例方法则需调用CreateDelegate重载的带实例对象参数的方法! Delegate delegateInstance = Delegate.CreateDelegate(delegateInfo, obj, methodInfo); return delegateInstance.DynamicInvoke(paras); } //获取事件,注意获取事件需要设置绑定参数为实例和非public,此处我也不清楚事件为什么作为非公有参数。。。 private static object GetEvent(string classFullName, string eventName, params object[] paras) { Type type = Type.GetType(classFullName); object obj = Activator.CreateInstance(type); EventInfo eventInfo = type.GetEvent(eventName); eventInfo.AddEventHandler(obj, new Class1.Fool((string str) => { return 400; })); eventInfo.AddEventHandler(obj, new Class1.Fool((string str) => { return 800; })); MulticastDelegate multicasDelegate = (MulticastDelegate)type.GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj); foreach (Delegate dele in multicasDelegate.GetInvocationList()) { Console.WriteLine(dele.Method.Name); object c = dele.DynamicInvoke(paras); Console.WriteLine("{0}", c); } Console.WriteLine(eventInfo.RaiseMethod); return multicasDelegate; } } }

    在获取事件的时候对于变量获取绑定标志的设定是BindingFlags.Instance | BindingFlags.NonPublic,这里我也不清

    楚为什么事件是非公有的,但如果设定为公有是获取不到事件的,其次关于委托的delegate关键字,其实是为了在编译 时自动生成一个继承于MulticastDelegate的委托类,所以所有委托都是从这个类继承下来的,再往上则是我们熟悉的 Delegate类,在解析件时,我们应该获取到需要的类实例,将其通过MulticastDelegate分解为委托链,通过 DynamicInvoke调用各委托绑定的方法即可。

    转载请注明原文地址: https://ju.6miu.com/read-3387.html

    最新回复(0)