您的位置:首页 > 编程语言 > VB

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

2005-12-14 13:51 411 查看

第一章 反射

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

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

一、 加载程序集

1、 加载程序集

Assembly类定义在System.Reflection中,可以使用Assembly.Load和Assembly.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、 [/b]使用Activator[/b]类创建一个实例[/b]

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

object instance = Activator.CreateInstance(reflectedClass);

2、 [/b]动态调用一个构造函数[/b]

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

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

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

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

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

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

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

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

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

PropertyInfo [] propertys = reflectedClass.GetProperties();

3、 [/b]传递方法参数[/b]

//传递方法参数

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继承并重写方法BindToMethod、BindToField、SelectMethod、SelectProperty和ChangeType。

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();

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

//第二个参数是位模BindingFlags(InvokeMethod告知反射在查找方法;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.GetMember和Type.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、 [/b]反射公共字段[/b]

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、 [/b]反射非公共字段[/b]

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、 [/b]实现一个简单自定义绑定器[/b]

反射可通过绑定器进行值的转换,而且绑定器也被用来将字段绑定到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.SelectPropery、BindToMethod、BindToField、RecordArgumentArray和SelectMethod的一个实现。

6、 反射事件

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

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

//通过EventInfo对象调用AddEventHander。AddEventHander需要与实例相关联的处理程序对象,并且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

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: