[C#]快速將弱型別的property轉成強型別的方式

[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();
	}
}