話題從今天TerryLee關於MVC的一段代碼說起:
protected void Application_Start()
{
RouteTable.Routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
請注意new { controller = "Home", action = "Index", id = "" }參數,它是C#3.0引入的匿名型別。 由於匿名型別是由編譯器自動產生的類型,MapRoute在編譯時間並不知道其確切類 型,而是在運行時通過反射解析其屬性來擷取資訊。這種方式在文法上顯得優雅 簡潔,它就是所謂的突變賦值(Mutantic Assignment)。
平常我們修改一個form對象的屬性需要若干的指派陳述式:
form.Text = “Hello World”;
form.Top = 100;
form.Left = 200;
如果C#支援突變複製,就可以像這樣一句話搞定:
form := new {Text = “Hello World”, Top = 100, Left = 200};
這樣是不是變得簡潔優雅了?可惜現在C#還沒有對突變賦值運算子 :=的支援 。從更大的層面上,更可惜的是C#運算子多載依然有諸多限制,也沒有像Boo語 言支援的syntax macro。期待在將來的C#中,我們能進行直接定製語言的文法, 讓代碼更加優雅簡潔。但現在我們不得以,退而求其次,只能嘗試在C#3.0中用 擴充方法類比突變賦值功能:
public static class Mutant
{
public static void MAssign(this object target, object source)
{
foreach (PropertyInfo pi1 in source.GetType ().GetProperties())
{
if (!pi1.CanRead) continue;
PropertyInfo pi2 = target.GetType ().GetProperty(pi1.Name, pi1.PropertyType);
if (null == pi2 || !pi2.CanWrite) continue;
pi2.SetValue(target, pi1.GetValue(source, null), null);
}
}
}
上面對object類定義了MAssign擴充方法,通過反射擷取和設定屬性值類比突 變賦值。這樣,我們就可以對任意對象進行突變賦值了:
form.MAssign(new {Text = “Hello World”, Top = 100, Left = 200});