C#之反射

最近在看反射就把获取各种常用类型变量的方法总结了一遍。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调用各委托绑定的方法即可。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值