高效地根據屬性名獲取某對象的屬性值


終於開通了博客。以后,我就把自己平時學習心得發上來,mark……

我們在一些開發任務中,時常遇到一種情況,就是我們需要根據一個對象的屬性名稱,去獲取這個屬性的值,或者是設置值。

那么,我們通常想到的方法是反射,這是可行的。但是性能不高。以下,為大家介紹一種高性能的方法。

請看代碼:

查看代碼
 1     /// <summary>
 2     /// 動態訪問對象
 3     /// </summary>
 4     /// <typeparam name="T">要訪問的對象的數據類型</typeparam>
 5     public class PropertyAccess<T>
 6     {
 7         private static Func<object, string, object> _getValueDelegate;
 8         private static Action<object, string, object> _setValueDelegate;
 9 
10         /// <summary>
11         /// 獲取指定對象的指定屬性的值

12         /// </summary>
13         /// <param name="instance">要獲取屬性值的對象</param>
14         /// <param name="memberName">要獲取的屬性的名稱</param>
15         /// <returns></returns>
16         public object GetValue(T instance, string memberName)
17         {
18             return _getValueDelegate(instance, memberName);
19         }
20 
21         /// <summary>
22         /// 為指定對象的指定屬性設置值。
23         /// </summary>
24         /// <param name="instance">要設置屬性的對象</param>
25         /// <param name="memberName">要設置的屬性名</param>
26         /// <param name="newValue">要設置的值</param>
27         public void SetValue(T instance, string memberName, object newValue)
28         {
29             _setValueDelegate(instance, memberName, newValue);
30         }
31 
32         /// <summary>
33         /// 實例化 <see cref="PropertyAccess&lt;T&gt;"/>34         /// </summary>
35         static PropertyAccess()
36         {
37             _getValueDelegate = GenerateGetValue();
38             _setValueDelegate = GenerateSetValue();
39         }
40 
41         /// <summary>
42         /// 構建讀取值函數
43         /// </summary>
44         /// <returns></returns>
45         private static Func<object, string, object> GenerateGetValue()
46         {
47             var type = typeof(T);
48             var instance = Expression.Parameter(typeof(object), "instance");
49             var memberName = Expression.Parameter(typeof(string), "memberName");
50             var nameHash = Expression.Variable(typeof(int), "nameHash");
51             var calHash = Expression.Assign(nameHash, Expression.Call(memberName, typeof(object).GetMethod("GetHashCode")));
52             var cases = new List<SwitchCase>();
53             foreach (var propertyInfo in type.GetProperties())
54             {
55                 var property = Expression.Property(Expression.Convert(instance, typeof(T)), propertyInfo.Name);
56                 var propertyHash = Expression.Constant(propertyInfo.Name.GetHashCode(), typeof(int));
57 
58                 cases.Add(Expression.SwitchCase(Expression.Convert(property, typeof(object)), propertyHash));
59             }
60             var switchEx = Expression.Switch(nameHash, Expression.Constant(null), cases.ToArray());
61             var methodBody = Expression.Block(typeof(object), new[] { nameHash }, calHash, switchEx);
62 
63             return Expression.Lambda<Func<object, string, object>>(methodBody, instance, memberName).Compile();
64         }
65 
66         /// <summary>
67         /// 構建設置屬性值函數
68         /// </summary>
69         /// <returns></returns>
70         private static Action<object, string, object> GenerateSetValue()
71         {
72             var type = typeof(T);
73             var instance = Expression.Parameter(typeof(object), "instance");
74             var memberName = Expression.Parameter(typeof(string), "memberName");
75             var newValue = Expression.Parameter(typeof(object), "newValue");
76             var nameHash = Expression.Variable(typeof(int), "nameHash");
77             var calHash = Expression.Assign(nameHash, Expression.Call(memberName, typeof(object).GetMethod("GetHashCode")));
78             var cases = new List<SwitchCase>();
79             foreach (var propertyInfo in type.GetProperties())
80             {
81                 // 屬性必須可寫
82                 if (!propertyInfo.CanWrite)
83                 {
84                     continue;
85                 }
86                 var property = Expression.Property(Expression.Convert(instance, typeof(T)), propertyInfo.Name);
87                 var setValue = Expression.Assign(property, Expression.Convert(newValue, propertyInfo.PropertyType));
88                 var propertyHash = Expression.Constant(propertyInfo.Name.GetHashCode(), typeof(int));
89 
90                 cases.Add(Expression.SwitchCase(Expression.Convert(setValue, typeof(object)), propertyHash));
91             }
92             var switchEx = Expression.Switch(nameHash, Expression.Constant(null), cases.ToArray());
93             var methodBody = Expression.Block(typeof(object), new[] { nameHash }, calHash, switchEx);
94 
95             return Expression.Lambda<Action<object, string, object>>(methodBody, instance, memberName, newValue).Compile();
96         }
97     }


OK,不廢話,以下代碼演示如何使用。

 

查看代碼
1 PropertyAccess<MyClass> propertyAccess=new PropertyAccess<MyClass>();
2 MyClass some=new MyClass();
3 some.TestProperty="yeaicc ,你敢不敢獲取到?";
4 object obj=propertyAccess.GetValue(some,"TestProperty");
5 // obj就是你所獲取的值了。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM