終於開通了博客。以后,我就把自己平時學習心得發上來,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就是你所獲取的值了。