話題從今天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});