在前例中,我們使用了 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 在行為了更為奇特,它具有動態物件的特性,卻保有繼承的概念。其實,動態語言也是可以繼承的,只是我們寫靜態語言習慣了,以為繼承是靜態語言的特性罷了。
沒有留言:
張貼留言