资源描述
FieldInfo..::.GetValue 方法
在派生类中被重写时,返回给定对象支持的字段的值。
命名空间: System.Reflection
程序集: mscorlib(在 mscorlib.dll 中)
如果该字段是静态的,则忽略 obj。对于非静态字段,obj 应是继承或声明该字段的类的实例。请注意,GetValue 的返回类型为 Object。例如,如果此字段包含一个 Boolean 基元值,则返回带有相应 Boolean 值的 Object 的实例。在返回该值以前,GetValue 将检查用户是否有访问权限。
静态字段: obj.GetType().GetField(字段名).GetValue(null);
实例非静态字段:typeof(类名).GetField(字段名,BindingFlags标识).GetValue(对象实例变量);
示例:获取静态字段的值
class MyClass
{
public static String val = "test";
public static void Main()
{
FieldInfo myf = typeof(MyClass).GetField("val");
Console.WriteLine(myf.GetValue(null));
val = "hi";
Console.WriteLine(myf.GetValue(null));
}
}
示例:获取对象实例的字段值
public class MyClass
{
public string myFieldA;
public string myFieldB;
public MyClass()
{
myFieldA = "A public field";
myFieldB = "Another public field";
}
}
public class FieldInfo_GetValue
{
public static void Main()
{
MyClass myInstance = new MyClass();
Type myType = typeof(MyClass);
try
{
// Get the FieldInfo of MyClass.
FieldInfo[] myFields = myType.GetFields(BindingFlags.Public
| BindingFlags.Instance);
Console.WriteLine("\n显示{0}类型实例各字段的值.\n", myType);
for(int i = 0; i < myFields.Length; i++)
{
Console.WriteLine("The value of {0} is: {1}",
myFields[i].Name, myFields[i].GetValue(myInstance));
}
}
catch(Exception e)
{
Console.WriteLine("Exception : {0}", e.Message);
}
}
}
下面举一个很实用的例子
有一个控件对象,它拥有Click事件,用户给Click事件添加了事件响应函数(EventHandler)。现在需要用一个扩展的自定义控件来通过代码方式动态替换现有控件。这样,即需要将原控件的事件处理函数复制过来。而事件对象不能被复制,只能通过反射的方式来实现。
深入分析:控件的Click事件定义方式可能如下。其中Events为EventHandlerList类型的集合对象,用来存储所有事件(在System.ComponentModel.Component中定义)。EventClick为object类型的对象,作为区分各类Event的key。
订阅和取消事件的实现方式如下
public event EventHandler Click
{
add { base.Events.AddHandler(EventClick, value); }
remove { base.Events.RemoveHandler(EventClick, value); }
}
EventClick定义如下
internal static readonly object EventClick;
EventHandlerList类中有一个特殊的方法:Find,定义如下
public sealed class EventHandlerList : ...
{
...
private ListEntry Find(object key);
...
private sealed class ListEntry
{
...
internal Delegate handler;
...
}
}
实际上,我们可以按如下方式获得EventHandler
control.Events.Find( control.EventClick ).handler
然后,由于封装的原因,我们无法直接执行如上调用。因此,反射发挥作用了:
var handler = (EventHandler) GetDelegate( toolStripButton, "EventClick" );
private static object GetDelegate( Component issuer, string keyName )
{
// 获取某类事件的Key
var key = issuer
.GetType( )
.GetField( keyName, BindingFlags.Static |
BindingFlags.NonPublic | BindingFlags.FlattenHierarchy )
.GetValue( null );
// 获取事件链表
var events = typeof( Component )
.GetField( "events", BindingFlags.Instance | BindingFlags.NonPublic )
.GetValue( issuer );
// 获取Find方法,并调用它获取Key对应的事件处理实体
var listEntry = typeof( EventHandlerList )
.GetMethod( "Find", BindingFlags.NonPublic | BindingFlags.Instance )
.Invoke( events, new object[] { key } );
// 获得处理事件的委托对象
var handler = listEntry
.GetType( )
.GetField( "handler", BindingFlags.Instance | BindingFlags.NonPublic )
.GetValue( listEntry );
return handler;
}
可通过如下方法列出所有事件类型:
private static IEnumerable<string> GetEventKeysList( Component issuer )
{
return
from key in issuer.GetType( ).GetFields( BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy )
where key.Name.StartsWith( "Event" )
select key.Name;
}
展开阅读全文