C#的動態對象的屬性實現比較簡單,如果要實現動態語言那種動態方法就比較困難,因為對於dynamic對象,擴展方法,匿名方法都是不能用直接的,這里還是利用對象和委托來模擬這種動態方法的實現,看起來有點JavaScript的對象味道:
1)定義一個委托,參數個數可變,參數都是object類型:這里的委托多有個dynamic參數,代表調用這個委托的動態對象本身.
1 public delegate object MyDelegate(dynamic Sender, params object[] PMs);
2)定義一個委托轉載對象,因為dynamic對象不能直接用匿名方法,這里用對象去承載:
1 public class DelegateObj 2 { 3 private MyDelegate _delegate; 4 5 public MyDelegate CallMethod 6 { 7 get { return _delegate; } 8 } 9 private DelegateObj(MyDelegate D) 10 { 11 _delegate = D; 12 } 13 /// <summary> 14 /// 構造委托對象,讓它看起來有點javascript定義的味道. 15 /// </summary> 16 /// <param name="D"></param> 17 /// <returns></returns> 18 public static DelegateObj Function(MyDelegate D) 19 { 20 return new DelegateObj(D); 21 } 22 }
3) 定義一個動態對象:
1 public class DynObj : DynamicObject 2 { 3 //保存對象動態定義的屬性值 4 private Dictionary<string, object> _values; 5 public DynObj() 6 { 7 _values = new Dictionary<string, object>(); 8 } 9 /// <summary> 10 /// 獲取屬性值 11 /// </summary> 12 /// <param name="propertyName"></param> 13 /// <returns></returns> 14 public object GetPropertyValue(string propertyName) 15 { 16 if (_values.ContainsKey(propertyName) == true) 17 { 18 return _values[propertyName]; 19 } 20 return null; 21 } 22 /// <summary> 23 /// 設置屬性值 24 /// </summary> 25 /// <param name="propertyName"></param> 26 /// <param name="value"></param> 27 public void SetPropertyValue(string propertyName,object value) 28 { 29 if (_values.ContainsKey(propertyName) == true) 30 { 31 _values[propertyName] = value; 32 } 33 else 34 { 35 _values.Add(propertyName, value); 36 } 37 } 38 /// <summary> 39 /// 實現動態對象屬性成員訪問的方法,得到返回指定屬性的值 40 /// </summary> 41 /// <param name="binder"></param> 42 /// <param name="result"></param> 43 /// <returns></returns> 44 public override bool TryGetMember(GetMemberBinder binder, out object result) 45 { 46 result = GetPropertyValue(binder.Name); 47 return result == null ? false : true; 48 } 49 /// <summary> 50 /// 實現動態對象屬性值設置的方法。 51 /// </summary> 52 /// <param name="binder"></param> 53 /// <param name="value"></param> 54 /// <returns></returns> 55 public override bool TrySetMember(SetMemberBinder binder, object value) 56 { 57 SetPropertyValue(binder.Name, value); 58 return true; 59 } 60 /// <summary> 61 /// 動態對象動態方法調用時執行的實際代碼 62 /// </summary> 63 /// <param name="binder"></param> 64 /// <param name="args"></param> 65 /// <param name="result"></param> 66 /// <returns></returns> 67 public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) 68 { 69 var theDelegateObj = GetPropertyValue(binder.Name) as DelegateObj; 70 if (theDelegateObj == null || theDelegateObj.CallMethod == null) 71 { 72 result = null; 73 return false; 74 } 75 result = theDelegateObj.CallMethod(this,args); 76 return true; 77 } 78 public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) 79 { 80 return base.TryInvoke(binder, args, out result); 81 } 82 }
測試代碼:
1 dynamic theObj = new DynObj(); 2 theObj.aaa = "this is a test";//動態屬性 3 //動態方法,這里不能沒法定義參數,調用的時候可以是任意多參數,具體參數類型和含義就只能自己去小心處理了. 4 theObj.show = DelegateObj.Function((s, pms) => 5 { 6 if (pms != null && pms.Length > 0) 7 { 8 MessageBox.Show(pms[0].ToString() + ":" + s.aaa); 9 } 10 else 11 { 12 MessageBox.Show(s.aaa); 13 } 14 return null; 15 } 16 ); 17 theObj.show("hello");