有時候,業務需求,需要根據屬性名稱設置屬性的值或者根據屬性名稱獲取屬性的值,原生的反射實現比較簡單,我想用Expression Tree來實現,寫成拓展方法,現在把它記錄下來,下次直接用。
/// <summary>
/// Object拓展方法,.Net4.0以上
/// </summary>
public static class ObjectExtension
{
/// <summary>
/// 根據屬性名獲取屬性值
/// </summary>
/// <typeparam name="T">對象類型</typeparam>
/// <param name="t">對象</param>
/// <param name="name">屬性名</param>
/// <returns>屬性的值</returns>
public static object GetPropertyValue<T>(this T t, string name)
{
Type type = t.GetType();
PropertyInfo p = type.GetProperty(name);
if (p == null)
{
throw new Exception(String.Format("該類型沒有名爲{0}的屬性", name));
}
var param_obj = Expression.Parameter(typeof(T));
var param_val = Expression.Parameter(typeof(object));
//轉成真實類型,防止Dynamic類型轉換成object
var body_obj = Expression.Convert(param_obj, type);
var body = Expression.Property(body_obj, p);
var getValue = Expression.Lambda<Func<T, object>>(body, param_obj).Compile();
return getValue(t);
}
/// <summary>
/// 根據屬性名稱設置屬性的值
/// </summary>
/// <typeparam name="T">對象類型</typeparam>
/// <param name="t">對象</param>
/// <param name="name">屬性名</param>
/// <param name="value">屬性的值</param>
public static void SetPropertyValue<T>(this T t, string name, object value)
{
Type type = t.GetType();
PropertyInfo p = type.GetProperty(name);
if (p == null)
{
throw new Exception(String.Format("該類型沒有名爲{0}的屬性", name));
}
var param_obj = Expression.Parameter(type);
var param_val = Expression.Parameter(typeof(object));
var body_obj = Expression.Convert(param_obj, type);
var body_val = Expression.Convert(param_val, p.PropertyType);
//獲取設置屬性的值的方法
var setMethod = p.GetSetMethod(true);
//如果只是只讀,則setMethod==null
if(setMethod!=null)
{
var body = Expression.Call(param_obj, p.GetSetMethod(), body_val);
var setValue = Expression.Lambda<Action<T, object>>(body, param_obj, param_val).Compile();
setValue(t, value);
}
}
}
public class Person
{
public string Name { set; get; }
}
class Program
{
static void Main(string[] args)
{
var person = new Person()
{
Name = "123"
};
dynamic p = new { Name = "123" };
object op = (object)p;
Console.WriteLine("Person 的Name屬性的值是{0}",person.GetPropertyValue("Name"));
person.SetPropertyValue("Name", "456");
Console.WriteLine("Person 的Name屬性的值修改後是{0}", person.Name);
Console.WriteLine("dynamic 的Name屬性的值是{0}", op.GetPropertyValue("Name"));
op.SetPropertyValue("Name", 456);
Console.WriteLine("dynamic 的Name屬性的值修改後是{0}", op.GetPropertyValue("Name"));
}
}
測試結果
Person 的Name屬性的值是123
Person 的Name屬性的值修改後是456
dynamic 的Name屬性的值是123
dynamic 的Name屬性的值修改後是123
請按任意鍵繼續. . .