Visual Basic .NET Power Coding 读书笔记之第四章 反射
第一章 反射
反射就是动态发现类型信息的能力。“动态”是指在运行时处理一些信息,而这些信息在设计时是未知的。
反射支持类似于后期绑定(源于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、 使用Activator类创建一个实例
Activator类支持动态创建.NET程序集和COM对象。Activator类有4个静态方法,CreateComInstanceForm、CreateInstance、CreateInstanceFrom和GetObject,它们能加载COM对象或者程序集,并能创建指定类型的实例。
object instance = Activator.CreateInstance(reflectedClass);
2、 动态调用一个构造函数
命名空间System.Reflection包含名称类似于membertypeInfo的类,这些类代表构造函数、方法、字段、属性、事件、成员(一般意义上的)和参数,分别被命名为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方法的复数形式获取一个特定类型的所有成员。
//读取一个类型的所有属性
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继承并重写方法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、 反射公共字段
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.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
}
}
出处:http://stwyhm.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。