.net反射的研究

  • 通过反射调用方法以及注册事件
    由于.NET中包含了类型的元数据,所以我们可以在运行时获得一个类型的详细信息,并对其做相应的操作。

    • 使用到的类

    为了使程序稍微复杂一点,我们假定一种场景。假设有三个类:学生类;导员类;校长类
    学生类和导员类在同一个Assembly中,校长类在另一个Assembly中,现在校长类需要使用反射的方法通过导员类来获得学生的信息。

  • Assembly A

  •     public class Student
        {
            private int age;
            private string name;
    
            private string grade="五年级二班";
            public string Grade
            {
                get { return grade; }
                set { grade = value; }
            }        
    
            public Student(int age,string name)
            {
                this.age = age;
                this.name = name;
            }
            public int Age
            {
                get { return age; }
                set { age = value; }
            }           
            public string Name
            {
                get { return name; }
                set { name = value; }
            }        
            //获得年级
            public string GetGrade()
            {
                return this.grade;
            }
        }
        public class StudentInstructor
        {
            //早恋事件
            public event EventHandler<LoveEventArgs> PuppyLove;
            public Student GetSudent1(int age,string name)
            {
                return new Student(age,name);
            }
            public static Student GetStudent2(int age, string name)
            {
                return new Student(age, name);
            }
            private void OnPuppyLove(object sender, LoveEventArgs e)
            {
                EventHandler<LoveEventArgs> eventHandler = PuppyLove;
                if (eventHandler != null)
                {
                    eventHandler(this, e);
                }
            }
    
            //这个函数用于触发早恋事件
            private void ReportToPresident()
            {
                LoveEventArgs lea=new LoveEventArgs ();
                Dictionary<string,int> stus=new Dictionary<string,int> ();
                stus.Add("王大锤",15);
                stus.Add("小美", 5);
                lea.StudentDic=stus;
                OnPuppyLove(this,lea);//触发事件
            }
        }
        public class LoveEventArgs : EventArgs
        {
            //包含早恋的南女学生
            public Dictionary<string, int> StudentDic { get; set; }
        }
    • Assembly B
      public class President
        {
            //通过调用Student类中的GetGrade()方法实现
            private void GetSudentGrade1(int age, string name)
            {
                Type type = Assembly.Load("assemblyName").GetType("assemblyName.StudentInstructor");
                MethodInfo mInfo = type.GetMethod("GetSudent1",new Type[]{typeof(int),typeof(string)});
                //通过调用StudentInstructor类中的GetSudent1获得学生类实例对象
                object sInstance = mInfo.Invoke(Activator.CreateInstance(type), new object[] { age, name });
    
                object sName = sInstance.GetType().GetMethod("GetGrade").Invoke(sInstance, null);
            }
            //通过调用Student类中的Grade属性实现
            private void GetSudentGrade2(int age, string name)
            {
                Type type = Assembly.Load("assemblyName").GetType("assemblyName.StudentInstructor");
                MethodInfo mInfo = type.GetMethod("GetSudent2", new Type[] { typeof(int), typeof(string) });
                //通过调用StudentInstructor类中的GetSudent2获得学生类实例对象,注意GetSudent2方法是静态的
                object sInstance = mInfo.Invoke(null, new object[] { age, name });
    
                object sName = sInstance.GetType().GetProperty("Grade").GetValue(sInstance, null);
            }
            /*当学生早恋时,导员就会向校长报告,然后校长会开除此学生以及他的另一半。让校长类通过反射注册导员类里面的PuppyLove事件,
             * 至于在学生类如何引发导员类中的
             * OnPuppyLove函数,比较简单,可以使用事件链完成。此处主要关注使用反射方法注册事件的方式
            */
            private void registerEvent()
            {
                Type type = Assembly.Load("assemblyName").GetType("assemblyName.StudentInstructor");
                //获得早恋事件信息                
                EventInfo eInfo = type.GetEvent("PuppyLove");
                //定义一个处理函数的委托
                Action<object, object> handler = OnOperation;
                Delegate convertedHandler = ConvertDelegate(handler, eInfo.EventHandlerType);
                eInfo.AddEventHandler(Activator.CreateInstance(type), convertedHandler);
            }
            //事件处理函数
            private void OnOperation(object sender, object args)
            {
                Type sendArgsType = args.GetType();
                PropertyInfo tranData = sendArgsType.GetProperty("StudentDic");
                object o = tranData.GetValue(args, null);
                Dictionary<string, int> stus = o as Dictionary<string, int>;
                foreach (var item in stus)
                {
                    Console.WriteLine(string.Format("{0}:{1}岁,
                    早恋开除",item.Key,item.Value));
                }
    
            }
            private Delegate ConvertDelegate(Delegate originalDelegate, 
                                                        Type targetDelegateType)
            {
                return Delegate.CreateDelegate( targetDelegateType,
                                                originalDelegate.Target,
                                                originalDelegate.Method);
            }
        }

    比较难于理解的就是使用反射的方式注册事件时,传递自定义时间参数的部分。
    由于我们在Assembly B中不可能认识Assembly A中的LoveEventArgs 类,所以需要获得一个
    符合事件签名的委托,这个功能是由ConvertDelegate方法完成的。originalDelegate.Target为校长类President;originalDelegate.Method为处理函数OnOperation

    • 将通过反射获得字典转换为目标字典
    从Assembly A中获得一个字典集合,例如  程序集A中有一个字典字段
    Dictionary<typeKeyA,typeValueA> fieldName
    在程序集B中通过反射的方式获得了这个字段的值,现在要将此字典转换为Dictionary<typeKeyB,typeValueB>fieldNameB,给如何实现呢?
    
    FieldInfo field = instance.GetType().GetField(fieldName);
    //将获得的字典转换为IDictionary类型,所有的泛型字典都实现了IDictionary接口
    IDictionary dictionary = (IDictionary)field.GetValue(instance);
    //在.net4.0及以后可以使用dynamic关键字
    Dictionary<typeKeyB, typeKeyB> newDictionary = 
        dictionary
        .Cast<dynamic>()
        .ToDictionary(entry => ConvertKeyA2B(entry.Key) ,
                      entry => ConvertValueA2B(entry.Value));
    //如果是.net4.0以前,需要使用下面的代码
    Dictionary<typeKeyB, typeKeyB> newDictionary = 
        CastDict(dictionary)
        .ToDictionary(entry => ConvertKeyA2B(entry.Key) ,
                      entry => ConvertValueA2B(entry.Value));
    private IEnumerable<DictionaryEntry> CastDict(IDictionary dictionary)
    {
        foreach (DictionaryEntry entry in dictionary)
        {
            yield return entry;
        }
    }                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShuSheng007

亲爱的猿猿,难道你又要白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值