2010年2月12日 星期五

C# 4.0: dynamic language (3)

前例中,我們使用了 ExpandoObject 做為動態物件,但 ExpandoObject 卻是不可被繼承的(sealed)。前例中的 Show 函式在執行時期被指定的。

   1: dynamic o = new ExpandoObject();
   2: o.Name = "aaa";
   3: o.Id = 3;
   4: o.Show = new Action(() => Console.WriteLine("Id = " + o.Id + ", Name = " + o.Name));
   5: o.Show();

如果,這樣的行為也可以有物件導向的行為就好了。這樣一來,Show函式就是固定的行為,而不是臨時被指定的,畢竟OO的概念在軟體重用上佔了一席之地,也是我們習慣的設計原則了。

於是,DynamicObject 就出現了。DynamicObject 透過繼承,將內部的物件以動態的方式呈現出來。當存取不存在的屬性、方法時,就會呼叫 DynamicObject 的 TrySetMember, TryGetMember, TryInvokeMember 等函式。

以下,就將上例改成 DynamicObject 來實作一次。

   1: class Program
   2: {
   3:   static void Main(string[] args)
   4:   {
   5:     dynamic o = new MyObj();
   6:     o.Name = "aaa";
   7:     o.Id = 3;
   8:     o.Show();
   9:   }
  10: }
  11:  
  12: class MyObj : DynamicObject
  13: {
  14:   Dictionary<string, object> _innerDictionary = new Dictionary<string, object>();
  15:   public override bool TrySetMember(SetMemberBinder binder, object value)
  16:   {
  17:     _innerDictionary[binder.Name] = value;
  18:     return true;
  19:   }
  20:   public void Show()
  21:   {
  22:     Console.WriteLine("Id = " + _innerDictionary["Id"] + ", Name = " + _innerDictionary["Name"]);
  23:   }
  24: }

由新版的例子來看,Show 函式已經是固定的行為了,一定會取得 Name 及 Id 的資料出來顯示。

DynamicObject 在行為了更為奇特,它具有動態物件的特性,卻保有繼承的概念。其實,動態語言也是可以繼承的,只是我們寫靜態語言習慣了,以為繼承是靜態語言的特性罷了。

沒有留言:

Share with Facebook