程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> Attribute+Reflection,提高代碼重用

Attribute+Reflection,提高代碼重用

編輯:C#入門知識

這篇文章兩個目的,一是開闊設計的思路,二是實例代碼可以拿來就用。

設計的思路來源於《Effective c#》第一版Item 24: 優先使用聲明式編程而不是命令式編程。特別的地方是,希望提供多個屬性的默認排序,而不僅僅只根據一個屬性,另外一點是,優先調用對象屬性實現了的IComparable<T>接口,如果沒有實現接口,才調用IComparable進行比較。排序類實現泛型,得到類型安全。

總的思路:Attribute用來裝飾我們想要獲取元數據的類,使用Reflection來提取元數據,根據提取到的元數據實現一些和對象無關的組件功能。

那麼,這個例子要實現的效果是用Attribute裝飾類對象,設置該對象的默認排序屬性,排序的時候,根據這些默認排序來進行排序。

 [DefaultSort( [] {,          ID { ;  
       Name { ;  
       Value { ;  
                  String.Format(  }

對於SortData對象來說,我們希望根據它的ID來排序,如果ID相等,再根據Name屬性來排序。像它的名字暗示的一樣,這是默認的行為,不需要我們實現SortData的IComparable<SortData>接口,將來要改變排序規則,只要修改DefaultSort中屬性名稱數組的內容就夠了,很方便。

原書中記錄的DefaultAttribute只能根據一個屬性名稱來排序,不夠實用,希望它像下面的類一樣,能記錄多個屬性的名稱。

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple=                  
                         {               { m_propNames =  
          DefaultSortAttribute(              m_propNames =    
          DefaultSortAttribute(              m_propNames =      }

注意仍然保留了只希望拿一個屬性來排序的構造函數,對類進行裝飾時,往類上面放[DefaultSort(new string[] {"ID", "Name"})] 和[DefaultSort("ID")]類似的聲明就夠了。

既然使用Attribute裝飾了類,就要知道這樣的元數據,下面需要采用Reflection讀到要排序的默認屬性名,相對於原書中的改進是,使用泛型和優先使用屬性的IComparable<T>接口來比較排序。

       
         DefaultSortComparer<T> : IComparer, IComparer<T>
                       m_reverse =             m_valueType =  
                      (  
          DefaultSortComparer(              m_reverse =             Type t =              m_valueType = 
             [] a = t.GetCustomAttributes((DefaultSortAttribute),  
             
              (a.Length !=                    
             DefaultSortAttribute sortName = a[]  
             [] propNames = 
             m_sortProps =  
             PropertyDescriptorCollection props = 
              ( i = ; i < propNames.Length; i++                  (PropertyDescriptor p                       (p.Name ==                     m_sortProps[i] =                          
          IComparer.Compare( left,                (HasNull(left, right) ==                    nullCompare = 
                  m_reverse ? -  
              (left.GetType() !=                   ArgumentException( 
              ((T).IsAssignableFrom(left.GetType()) ==                    ArgumentException( 
               
                         (m_valueType ==  && HasNull(x, y) ==                   nullCompare =                  m_reverse ? -  
              ( prop                   xValue =                  yValue = 
                  (HasNull(xValue, yValue) ==                       nullCompare = 
                      m_reverse ? -  
                 Type propType = 
                 
                  ((IComparable<>                      MethodInfo methodInfo = propType.GetMethods().FirstOrDefault(method => method.Name == 
                         && method.GetParameters().Length == 
                         && method.GetParameters()[].ParameterType == 
                      gretValue = ()methodInfo.Invoke(xValue,   
                      (gretValue == )  
                      m_reverse ? -  
                 IComparable xNonGeneric = xValue                  IComparable yNonGeneric = yValue  
                  (xNonGeneric ==                        ArgumentException( + prop.Name +  
                  retValue = 
                  (retValue == )  
                  m_reverse ? -  
                
          CompareWithNull( left,                ((left == ) && (right ==                    
              (left ==                   - 
                
          HasNull( left,                (left ==  || right ==                                    }

 

需要注意的是DefaultSortComparer<T>是泛型的,並實現了IComparer, IComparer<T>接口,實現了這兩個接口,才方便排序。


代碼寫貼了這麼多,用起來怎麼用呢。

  data1 =  SortData() { ID = , Name = , Value =   data2 =  SortData() { ID = , Name = , Value =   data3 =  SortData() { ID = , Name = , Value =   data4 =  SortData() { ID = , Name = , Value =  
 List<SortData> sortData =  List<SortData>     
 sortData.Sort( DefaultSortComparer<SortData>( 
 sortData.ForEach(data => Console.WriteLine(data));


結果就不獻丑了,經測試,能正常工作。

通過這個例子,就可以看到,要實現它的關鍵是,Attribute負責裝飾類,Reflection負責讀取特定Attribute裝飾後的元數據信息,實現和特定類類型無關的組件。一次Coding,多次復用。

希望大家多支持,以後會多放一些有意思的開箱即用的代碼上來。

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