终于开通了博客。以后,我就把自己平时学习心得发上来,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就是你所获取的值了。