Visual Basic .NET Power Coding 读书笔记之第四章 反射

 

第一章       反射

反射就是动态发现类型信息的能力。“动态”是指在运行时处理一些信息,而这些信息在设计时是未知的。

反射支持类似于后期绑定(源于COM)的能力,并且允许代码同未预知的代码交互。反射支持显式加载一个程序集、动态发现类型和类型成员的信息,以及调用这些类型和成员的操作。

一、      加载程序集

1、        加载程序集

Assembly类定义在System.Reflection中,可以使用Assembly.LoadAssembly.LoadFrom共享方法动态地加载程序集。Assembly.Load方法需要AssemblyName参数,参数AssemblyName由版本、文化和一个强名或者公钥组成。使用Assembly.LoadForm比较容易并可简单地提供程序集名称。

Assembly myAssembly = Assembly.LoadFrom("[Assembly Path]");

2、        调用被反射的方法

const string path = @"D:\日常文档\读书笔记\小绵羊\Visual Basic .Net Power Coding\Reflection\bin\Debug\Reflection.dll";

              //从固定的文件路径中加载程序集

              Assembly helloWorldAssembly = Assembly.LoadFrom(path);

              //从加载的程序集中获取一个类型,它之所以存在是因为我们已经编写了它。

              Type reflectedClass = helloWorldAssembly.GetType("HelloWorld.ReflectedClass");

              //简单调用了HelloWorld.ReflectedClass.HelloWorld方法

              //第一个参数是要调用的方法名

              //第二个参数是绑定标志,用来通知反射要寻找的内容

              //第三个参数是绑定器,这个简单示例不需要绑定器,所以设为null

//第四个参数是调用成员的实例,因为HelloWorld方法是静态的,所以不需要调用方法的类的实例,所以设为null

              //第五个参数是将传递的参数,因为HelloWorld方法是无参的,所以设为null

reflectedClass.InvokeMember("HelloWorld",BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,null,null,null);

3、        Type对象创建实例

1、 使用Activator类创建一个实例

Activator类支持动态创建.NET程序集和COM对象。Activator类有4个静态方法,CreateComInstanceFormCreateInstanceCreateInstanceFromGetObject,它们能加载COM对象或者程序集,并能创建指定类型的实例。

object instance = Activator.CreateInstance(reflectedClass);

2、 动态调用一个构造函数

命名空间System.Reflection包含名称类似于membertypeInfo的类,这些类代表构造函数、方法、字段、属性、事件、成员(一般意义上的)和参数,分别被命名为ConstrutorInfoMethodInfoFieldInfoEventInfoMemberInfoParameterInfo,每个类都是对其元素类型信息的面向对象的表示。System.Type类是准许进入的许可证。如果查询得到了具有任何类型信息的实例,就可以获得该类型中任意元素的类型信息。当然,不保证会得到程序集中的任何信息,因为安全也是一个要考虑的因素。

特性信息的处理有一点不同,通过任意System.Type对象的GetCustomAttributeGetCustomAttributes方法都能够查询特性信息。

              //使用了类型对象reflectedClass,并且查询单独的ConstructorInfo类型记录

//参数new System.Type[]{}告知GetConstructor方法要获取哪一个构造函数。而类型数组是为了与参数匹配。

ConstructorInfo constructorInfo = reflectedClass.GetConstructor(new System.Type[]{});

              //将一组符合的参数传递给构造函数

     object instance = constructorInfo.Invoke(new object[]{});

任何类型都可以不具有或者具有多个元素描述。为了反射实际情况,System.Type需要获得方法的复数形式,可使用Getmembertype方法的复数形式获取一个特定类型的所有成员。

//读取一个类型的所有属性

PropertyInfo [] propertys = reflectedClass.GetProperties();

3、 传递方法参数

//传递方法参数

ConstructorInfo constructorInfo = reflectedClass.GetConstructor(new System.Type[]{Type.GetType("string")});

object instance = constructorInfo.Invoke(new object[]{"this is a Parameter"});

二、      评论Binder

Binder类是一个必须对其继承才可使用的抽象类,绑定器用于执行类型转换。要创建绑定器,需要从System.Reflection.Binder继承并重写方法BindToMethodBindToFieldSelectMethodSelectPropertyChangeType

System.Type类具有DefaultBinder属性,当需要绑定器但不需要特别的绑定行为时就可以使用它。

1、        使用DefaultMemberAttribute

DefautlMemberAttribute用于类型并带有一个指明默认成员名称的字符串参数。能够通过InvokeMember调用默认成员,而不需要传递调用成员的名称。

调用代码:

//使用DefaultMemberAttribute

reflectedClass.InvokeMember("",BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,Type.DefaultBinder,null,null);

类声明代码:

     [DefaultMember("HelloWorld")]

     public class ReflectedClass

     {

         private string FMessage;

         public ReflectedClass()

         {

         }

 

         public ReflectedClass(string message)

         {

              this.FMessage = message;

         }

 

         public static string HelloWorld()

         {

              return "Hello World";

         }

 

         public string ShowMessage(string text)

         {

              return text + ",Hello World!";

         }

}

三、      反射成员

1、        反射方法

ReflectMembers instance = new ReflectMembers();

         Type type = instance.GetType();

         //第一个参数是成员名称

//第二个参数是位模BindingFlagsInvokeMethod告知反射在查找方法;NonPublic告知反射是在查找非公共方法;Instance则通知反射正在引用非静态成员)

//第三个参数是Binder参数,因为这里不需要进行任何数据转换,所以不需要绑定器,就用null表示

         //第四个参数是与调用成员相对应的对象

         //最后一个参数是传递给方法的参数组

type.InvokeMember("ProtectedMethod",BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,null,instance,new object[]{});

2、        反射参数

//获取方法元数据

         MethodInfo methodInfo = type.GetMethod("PublicFunction");

         //得到指定方法的参数集

         ParameterInfo [] parameterInfos = methodInfo.GetParameters();

             

         foreach(ParameterInfo parameterInfo in parameterInfos)

         {

              //获取的参数信息

              //parameterInfo.Name;

              //parameterInfo.ParameterType;

              //parameterInfo.IsOptional;

              //parameterInfo.Position;

              //parameterInfo.DefaultValue;

         }

3、        反射任何成员

可以分别使用Type.GetMemberType.GetMembers方法查询一个或一组MemberInfo对象。MemberInfo对象是特定类型记录的一种常用形式。

4、        反射属性

         //调用属性设置器

type.InvokeMember("PublicProperty",BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance,null,instance,new object[]{"this is Test"});

         //调用查询设置器

object value = type.InvokeMember("PublicProperty",BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance,null,instance,new object[]{});

5、        反射字段

1、 反射公共字段

type.InvokeMember("PublicField",BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance,null,instance,new object[]{"this is Test"});

object value = type.InvokeMember("PublicField",BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance,null,instance,new object[]{});

 

2、 反射非公共字段

type.InvokeMember("PrivateField",BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Instance,new SimpleBinder(),instance,new object [] {"13"});

object value = type.InvokeMember("PrivateField",BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance,null,instance,new object [] {});

3、 实现一个简单自定义绑定器

反射可通过绑定器进行值的转换,而且绑定器也被用来将字段绑定到ASP.NET Web页面中的控件上。

/// <summary>

/// 一个简单自定义绑定器

          /// </summary>

          public class SimpleBinder : Binder

          {

public override object ChangeType(object value, Type type, System.Globalization.CultureInfo culture)

              {

                   try

                   {

                        if(value.GetType() is string)

                        {

                            return Int32.Parse(value.ToString());

                        }

                        else

                        {

                             return value;

                        }

                   }

                   catch

                   {

                        return value;

                   }

              }

 

public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers)

              {

                   return null;

              }

 

public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] names, out object state)

              {

                   state = null;

                   return null;

              }

 

public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, System.Globalization.CultureInfo culture)

              {

                   return null;

              }

 

              public override void ReorderArgumentArray(ref object[] args, object state)

              {

              }

 

public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)

              {

                   return null;

              }

}

创建绑定器必须从System.Reflection.Binder继承并提供ChangeType.SelectProperyBindToMethodBindToFieldRecordArgumentArraySelectMethod的一个实现。

6、        反射事件

//通过调用GetEvent和命名事件获得EventInfo对象

EventInfo eventInfo = type.GetEvent("PublicEvent",BindingFlags.Public | BindingFlags.Instance);

//通过EventInfo对象调用AddEventHanderAddEventHander需要与实例相关联的处理程序对象,并且System.Delegate由符合EventHandler签名的方法地址构成和初始化。

eventInfo.AddEventHandler(instance,new EventHandler(Handler));

         //引发事件方法

         instance.DoEvent();

7、        反射自定义特性

Attribute [] attributes = typeof(Customer).GetCustomAttributes(true);

         foreach(Attribute attribute in attributes)

         {

              if(attribute is DescriptionAttribute)

              {

                   //code

              }

         }

posted @ 2005-12-14 13:51  文野  阅读(2373)  评论(7编辑  收藏  举报