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");