-
通过反射调用方法以及注册事件
由于.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; } }
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14815.html