程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#動態對象(dynamic)示例(實現方法和屬性的動態)

C#動態對象(dynamic)示例(實現方法和屬性的動態)

編輯:C#入門知識

C#的動態對象的屬性實現比較簡單,如果要實現動態語言那種動態方法就比較困難,因為對於dynamic對象,擴展方法,匿名方法都是不能用直接的,這裡還是利用對象和委托來模擬這種動態方法的實現,看起來有點javascript的對象味道:

1)定義一個委托,參數個數可變,參數都是object類型:這裡的委托多有個dynamic參數,代表調用這個委托的動態對象本身.


[csharp]
public delegate object MyDelegate(dynamic Sender, params object[] PMs); 
public delegate object MyDelegate(dynamic Sender, params object[] PMs);

2)定義一個委托轉載對象,因為dynamic對象不能直接用匿名方法,這裡用對象去承載:

[csharp]
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); 
        } 
    } 
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) 定義一個動態對象:

[csharp]
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); 
        } 
    } 
public class DynObj : DynamicObject
    {
        //保存對象動態定義的屬性值
        private Dictionary<string, object> _values;
        public DynObj()
        {
            _values = new Dictionary<string, object>();
        }
        /// <summary>
        /// 獲取屬性值 www.2cto.com
        /// </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);
        }
    }

應用測試代碼:

[csharp]
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"); 
 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.

 


摘自 hawksoft

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved