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