C#动态对象(dynamic)示例(实现方法和属性的动态)

C#的动态对象的属性实现比较简单,如果要实现动态语言那种动态方法就比较困难,因为对于dynamic对象,扩展方法,匿名方法都是不能用直接的,这里还是利用对象和委托来模拟这种动态方法的实现,看起来有点javascript的对象味道:

1)定义一个委托,参数个数可变,参数都是object类型:这里的委托多有个dynamic参数,代表调用这个委托的动态对象本身.

  1. publicdelegateobject MyDelegate(dynamic Sender, paramsobject[] PMs); 
public delegate object MyDelegate(dynamic Sender, params object[] PMs);

2)定义一个委托转载对象,因为dynamic对象不能直接用匿名方法,这里用对象去承载:

  1. publicclass 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.         publicstatic DelegateObj Function(MyDelegate D) 
  19.         { 
  20.             returnnew DelegateObj(D); 
  21.         } 
  22.     } 
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) 定义一个动态对象:

  1. publicclass 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.         publicobject GetPropertyValue(string propertyName) 
  15.         { 
  16.             if (_values.ContainsKey(propertyName) == true
  17.             { 
  18.                 return _values[propertyName]; 
  19.             } 
  20.             returnnull
  21.         } 
  22.         /// <summary> 
  23.         /// 设置属性值 
  24.         /// </summary> 
  25.         /// <param name="propertyName"></param> 
  26.         /// <param name="value"></param> 
  27.         publicvoid 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.         publicoverridebool TryGetMember(GetMemberBinder binder, outobject 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.         publicoverridebool TrySetMember(SetMemberBinder binder, object value) 
  56.         { 
  57.             SetPropertyValue(binder.Name, value); 
  58.             returntrue
  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.         publicoverridebool TryInvokeMember(InvokeMemberBinder binder, object[] args, outobject result) 
  68.         { 
  69.             var theDelegateObj = GetPropertyValue(binder.Name) as DelegateObj; 
  70.             if (theDelegateObj == null || theDelegateObj.CallMethod == null
  71.             { 
  72.                 result = null
  73.                 returnfalse
  74.             } 
  75.             result = theDelegateObj.CallMethod(this,args); 
  76.             returntrue
  77.         } 
  78.         publicoverridebool TryInvoke(InvokeBinder binder, object[] args, outobject result) 
  79.         { 
  80.             returnbase.TryInvoke(binder, args, out result); 
  81.         } 
  82.     } 
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);
        }
    }

应用测试代码:

  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.                returnnull
  15.            } 
  16.            ); 
  17.            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.

转自:http://blog.csdn.net/hawksoft/article/details/7534332