有时候,业务需求,需要根据属性名称设置属性的值或者根据属性名称获取属性的值,原生的反射实现比较简单,我想用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
请按任意键继续. . .