[C#]快速將弱型別的property轉成強型別的方式
在C#裡面使用property有兩種方式,一種就是我們定義的類別有屬性,這樣子我們可以用最方便的方式去使用,甚至用一些automapper或tinymap都可以很快速的幫我們轉換類別,但是如果是類似像DataRow取屬性的方式呢?如下例子
row["Name"]
像這種方式去取值的話,除了不好觀看這個物件有什麼屬性,因為是動態的,所以我們只能下偵錯並用Properites來看此物件到底有何屬性,所以最理想化我們都會定義好屬性對應,但有時候接一些微軟原生的,就是會遇到像這種取屬性的方式,比如ManagementBaseObject這個類別,一樣我們都只能用括號的方式去取屬性的值,那如何能把這種弱型別的屬性轉成我們所定義的物件呢?其實我們只要善用propertyinfo就可以達成這個需求了,以一個抓iis的information的例子,原本我們需要如下方式去取得物件的資訊
void Main()
{
var remoteOptions = new ConnectionOptions
{
EnablePrivileges = true,
Authentication = AuthenticationLevel.PacketPrivacy
Username="anson",
Password="password"
};
ManagementScope ms = new ManagementScope(
@"\\your ip\root\MicrosoftIISv2", remoteOptions);
ms.Connect();
ObjectQuery query = new ObjectQuery(@"SELECT * FROM IISApplicationPoolSetting");
ManagementObjectSearcher search = new ManagementObjectSearcher(ms, query);
var queryCollection = search.Get();
foreach (var element in queryCollection)
{
if (element["Name"].ToString().IndexOf(".NET v4.5") > -1)
{
element["Name"].Dump();
element["CPUAction"].Dump();
element["CPULimit"].Dump();
element["CPUResetInterval"].Dump();
element["MaxProcesses"].Dump();
element["LoadBalancerCapabilities"].Dump();
element["PeriodicRestartMemory"].Dump();
element["PeriodicRestartPrivateMemory"].Dump();
}
}
}
從此例子可以看得出來,是用字串的方式去取得,這樣子我們除了不知道裡面有多少屬性之外,如果打錯字的話,都會出現問題,所以善用propertyinfo來把上面的內容轉成強型別的方式吧,首先定義一個對應的類別
public class IISApplicationPoolSetting{
public string Name { get; set; }
public int CPUAction { get; set; }
public int CPULimit { get; set; }
public int CPUResetInterval { get; set; }
public int MaxProcesses { get; set; }
public int LoadBalancerCapabilities { get; set; }
public int PeriodicRestartMemory { get; set; }
public int PeriodicRestartPrivateMemory { get; set; }
}
接著定義一個方法,把property解析出來,並寫進我們想塞進的類別。
void SetItemFromRow<T>(T item, ManagementBaseObject row)
{
// go through each column
foreach (var c in row.Properties)
{
// find the property for the column
PropertyInfo p = item.GetType().GetProperty(c.Name);
// if exists, set the value
if (p != null)
{
p.SetValue(item, row[c.Name], null);
}
}
}
最後程式碼就變成如下的樣子囉
foreach (var element in queryCollection)
{
var iisInfo=new IISApplicationPoolSetting();
SetItemFromRow(iisInfo,element);
if(iisInfo.Name.IndexOf(".NET v4.5") > -1)
{
iisInfo.Name.Dump();
iisInfo.CPUAction.Dump();
iisInfo.CPULimit.Dump();
iisInfo.CPUResetInterval.Dump();
iisInfo.MaxProcesses.Dump();
iisInfo.LoadBalancerCapabilities.Dump();
iisInfo.PeriodicRestartMemory.Dump();
iisInfo.PeriodicRestartPrivateMemory.Dump();
}
}