摘要:[ASP.NET] 利用反射方法(Type.InvokeMember)取得不同資料物件屬性
前言
反射方法算是 C# 比較進階的使用,Type.InvokeMember 方法可以在執行時期動態繫結物件屬性或方法,以下舉個例子來說明。
範例
我有兩個不同的資料物件和一個輸出方法,兩個資料物件將由使用者在執行時期的操作而產生對應的資料物件,並且使用同一個輸出方法來列印資料物件的值,該怎麼做呢? 下面來實作一下。
先建立兩個 Value Object:
UserVo
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<string> PropertyNames
{
get { return _PropertyNames; }
set { _PropertyNames = value; }
}
public object GetPropertyValue(string propName)
{
switch (propName)
{
case "name":
return name;
default:
return "";
}
}
}
ProductVo
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<string> _PropertyNames = new List<string>();
public List<string> 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 方法:
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<string> names = (List<string>)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 }) + "</br>");
}
}
完成後,實際執行結果如下:
另外補充,在 .NET Framework 4.0 C# 中多了 dynamic 型別,如果在此將 PrintData 的傳入參數改成 dynamic 型別後,呼叫成員的方法就可以不使用反射的方式,可以直接叫用該方法即可。
範例下載
參考資料
Type.InvokeMember 方法 (String, BindingFlags, Binder, Object, Object[])
以上文章敘述如有錯誤及觀念不正確,請不吝嗇指教
如有侵權內容也請您與我反應~謝謝您 :)