C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点javascript的对象味道:
1)定义一个委托,参数个数可变,参数都是object类型:这里的委托多有个dynamic参数,代表调用这个委托的动态对象本身.
- publicdelegateobject MyDelegate(dynamic Sender, paramsobject[] PMs);
public delegate object MyDelegate(dynamic Sender, params object[] PMs);
2)定义一个委托转载对象,因为dynamic对象不能直接用匿名方法,这里用对象去承载:
- publicclass DelegateObj
- {
- private MyDelegate _delegate;
- public MyDelegate CallMethod
- {
- get { return _delegate; }
- }
- private DelegateObj(MyDelegate D)
- {
- _delegate = D;
- }
- /// <summary>
- /// 构造委托对象,让它看起来有点javascript定义的味道.
- /// </summary>
- /// <param name="D"></param>
- /// <returns></returns>
- publicstatic DelegateObj Function(MyDelegate D)
- {
- returnnew DelegateObj(D);
- }
- }
public class DelegateObj { private MyDelegate _delegate; public MyDelegate CallMethod { get { return _delegate; } } private DelegateObj(MyDelegate D) { _delegate = D; } /// <summary> /// 构造委托对象,让它看起来有点javascript定义的味道. /// </summary> /// <param name="D"></param> /// <returns></returns> public static DelegateObj Function(MyDelegate D) { return new DelegateObj(D); } }
3) 定义一个动态对象:
- publicclass DynObj : DynamicObject
- {
- //保存对象动态定义的属性值
- private Dictionary<string, object> _values;
- public DynObj()
- {
- _values = new Dictionary<string, object>();
- }
- /// <summary>
- /// 获取属性值
- /// </summary>
- /// <param name="propertyName"></param>
- /// <returns></returns>
- publicobject GetPropertyValue(string propertyName)
- {
- if (_values.ContainsKey(propertyName) == true)
- {
- return _values[propertyName];
- }
- returnnull;
- }
- /// <summary>
- /// 设置属性值
- /// </summary>
- /// <param name="propertyName"></param>
- /// <param name="value"></param>
- publicvoid SetPropertyValue(string propertyName,object value)
- {
- if (_values.ContainsKey(propertyName) == true)
- {
- _values[propertyName] = value;
- }
- else
- {
- _values.Add(propertyName, value);
- }
- }
- /// <summary>
- /// 实现动态对象属性成员访问的方法,得到返回指定属性的值
- /// </summary>
- /// <param name="binder"></param>
- /// <param name="result"></param>
- /// <returns></returns>
- publicoverridebool TryGetMember(GetMemberBinder binder, outobject result)
- {
- result = GetPropertyValue(binder.Name);
- return result == null ? false : true;
- }
- /// <summary>
- /// 实现动态对象属性值设置的方法。
- /// </summary>
- /// <param name="binder"></param>
- /// <param name="value"></param>
- /// <returns></returns>
- publicoverridebool TrySetMember(SetMemberBinder binder, object value)
- {
- SetPropertyValue(binder.Name, value);
- returntrue;
- }
- /// <summary>
- /// 动态对象动态方法调用时执行的实际代码
- /// </summary>
- /// <param name="binder"></param>
- /// <param name="args"></param>
- /// <param name="result"></param>
- /// <returns></returns>
- publicoverridebool TryInvokeMember(InvokeMemberBinder binder, object[] args, outobject result)
- {
- var theDelegateObj = GetPropertyValue(binder.Name) as DelegateObj;
- if (theDelegateObj == null || theDelegateObj.CallMethod == null)
- {
- result = null;
- returnfalse;
- }
- result = theDelegateObj.CallMethod(this,args);
- returntrue;
- }
- publicoverridebool TryInvoke(InvokeBinder binder, object[] args, outobject result)
- {
- returnbase.TryInvoke(binder, args, out result);
- }
- }
public class DynObj : DynamicObject { //保存对象动态定义的属性值 private Dictionary<string, object> _values; public DynObj() { _values = new Dictionary<string, object>(); } /// <summary> /// 获取属性值 /// </summary> /// <param name="propertyName"></param> /// <returns></returns> public object GetPropertyValue(string propertyName) { if (_values.ContainsKey(propertyName) == true) { return _values[propertyName]; } return null; } /// <summary> /// 设置属性值 /// </summary> /// <param name="propertyName"></param> /// <param name="value"></param> public void SetPropertyValue(string propertyName,object value) { if (_values.ContainsKey(propertyName) == true) { _values[propertyName] = value; } else { _values.Add(propertyName, value); } } /// <summary> /// 实现动态对象属性成员访问的方法,得到返回指定属性的值 /// </summary> /// <param name="binder"></param> /// <param name="result"></param> /// <returns></returns> public override bool TryGetMember(GetMemberBinder binder, out object result) { result = GetPropertyValue(binder.Name); return result == null ? false : true; } /// <summary> /// 实现动态对象属性值设置的方法。 /// </summary> /// <param name="binder"></param> /// <param name="value"></param> /// <returns></returns> public override bool TrySetMember(SetMemberBinder binder, object value) { SetPropertyValue(binder.Name, value); return true; } /// <summary> /// 动态对象动态方法调用时执行的实际代码 /// </summary> /// <param name="binder"></param> /// <param name="args"></param> /// <param name="result"></param> /// <returns></returns> public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { var theDelegateObj = GetPropertyValue(binder.Name) as DelegateObj; if (theDelegateObj == null || theDelegateObj.CallMethod == null) { result = null; return false; } result = theDelegateObj.CallMethod(this,args); return true; } public override bool TryInvoke(InvokeBinder binder, object[] args, out object result) { return base.TryInvoke(binder, args, out result); } }
应用测试代码:
- dynamic theObj = new DynObj();
- theObj.aaa = "this is a test";//动态属性
- //动态方法,这里不能没法定义参数,调用的时候可以是任意多参数,具体参数类型和含义就只能自己去小心处理了.
- theObj.show = DelegateObj.Function((s, pms) =>
- {
- if (pms != null && pms.Length > 0)
- {
- MessageBox.Show(pms[0].ToString() + ":" + s.aaa);
- }
- else
- {
- MessageBox.Show(s.aaa);
- }
- returnnull;
- }
- );
- theObj.show("hello");
dynamic theObj = new DynObj(); theObj.aaa = "this is a test";//动态属性 //动态方法,这里不能没法定义参数,调用的时候可以是任意多参数,具体参数类型和含义就只能自己去小心处理了. theObj.show = DelegateObj.Function((s, pms) => { if (pms != null && pms.Length > 0) { MessageBox.Show(pms[0].ToString() + ":" + s.aaa); } else { MessageBox.Show(s.aaa); } return null; } ); theObj.show("hello");
虽然看起来上面有点Js定义对象方法的味道,但由于C#是静态语言,提供的动态模拟机制还是有限的,看起来是动态,但所有的值存放和方法都需要自己写代码去处理.
以上代码在vs2010,windows 2008 server,框架4.0 上测试OK.