使用Type.InvokeMember方法可以在执行时期动态系结对象属性或方法,
举个例子来说明,
我有两个不同的数据对象和一个输出方法,两个数据对象将由使用者在执行时期的操作而产生对应的数据对象,
并且使用同一个输出方法来打印数据对象的值,该怎么做呢? 下面来实作一下。
先建立两个 value object
public class UserVo
{
private string _name;
public string name
{
get { return _name; }
set {
_name = value;
_PropertyNames.Add("name");
}
}
private List<string> _PropertyNames = new List<string>();
public List PropertyNames
{
get { return _PropertyNames; }
set { _PropertyNames = value; }
}
public object GetPropertyValue(string propName)
{
switch (propName)
{
case "name":
return name;
default:
return "";
}
}
}
public class ProductVo
{
private int _pid;
public int pid
{
get { return _pid; }
set {
_pid = value;
_PropertyNames.Add("pid");
}
}
private string _proName;
public string proName
{
get { return _proName; }
set {
_proName = value;
PropertyNames.Add("proName");
}
}
private List _PropertyNames = new List();
public List PropertyNames
{
get { return _PropertyNames; }
set { _PropertyNames = value; }
}
public object GetPropertyValue(string propName)
{
switch (propName)
{
case "pid":
return pid;
case "proName":
return proName;
default:
return "";
}
}
}
在这两个数据对象中,除了本身的一些属性之外,我额外增加了 PropertyNams属性跟 GetPropertyValue方法PropertyNams 属性用来存放有给予值的属性名称以便于之后调用。
GetPropertyValue 方法用来取得与属性名称对应之值。
在将数据对象处理完成后,就要来实际使用 InvokeMember 方法在执行时期将产生的对象属性显示,建立一个 aspx 网页,并在画面上拖入两个按钮

切换到后置程序代码画面,在两个按钮事件中分别建立不同的数据对象,并将对象传至PrintData方法www.it165.net
protected void Button1_Click(object sender, EventArgs e)
{
UserVo myVo = new UserVo();
myVo.name = "Arvin";
PrintData(myVo);
}
protected void Button2_Click(object sender, EventArgs e)
{
ProductVo myVo = new ProductVo();
myVo.pid = 101000001;
myVo.proName = "Product_101";
PrintData(myVo);
}
在此使用 Type.InvokeMember 方法 (String, BindingFlags, Binder, Object, Object[])
语法如下:
public Object InvokeMember(
string name,
BindingFlags invokeAttr,
Binder binder,
Object target,
Object[] args
)
• name: 要呼叫的属性或方法名称
• invokeAttr: 位屏蔽,如BindingFlags.GetProperty(取属性)或BindingFlags.InvokeMethod(叫用方法)等...
• binder: 定义一组属性并启用系结的对象
• target: 要呼叫的该对象成员
• args: 要传入呼叫的成员的自变量数组
在PrintData方法中,先使用 getType() 取得该对象型别,因为了让PrintData方法于不同的数据对象都能使用,传入的数据对象是使用object去接收,
取得了 objType 之后,使用反射的方式将数据对象的PropertyNames属性取得,invokeAttr参数使用的是 BindingFlags.GetProperty
而取得了PropertyNames后就可以使用循环将资料读出,而在读取数据时将 invokeAttr参数改成 BindingFlags.InvokeMethod 则变成呼叫方法
private void PrintData(object objVo)
{
Type objType = objVo.GetType();
// 取得属性名称集合
List names = (List)objType.InvokeMember("PropertyNames", System.Reflection.BindingFlags.GetProperty, null, objVo, new object[] { });
// 将所有属性值印出
foreach (string name in names)
{
Response.Write(objType.InvokeMember("GetPropertyValue", System.Reflection.BindingFlags.InvokeMethod, null, objVo, new object[] { name }) + "
");
}
}
完成后,实际执行结果如下

另外补充一下,在.NET Framework 4.0 C#中多了 dynamic 型别,
如果在此将PrintData的传入参数改成 dynamic 型别后,呼叫成员的方法就可以不使用反射的方式,
可以直接叫用该方法即可。