Expression 获取,设置属性的值

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个示例。假设我们有一个对象 User,它有两个属性,分别是 name 和 age。我们想要获取它的 name 属性,可以使用 AbstractFlowableVariableExpressionFunction。具体步骤如下: 1. 创建一个 User 对象,并设置 name 和 age 属性。 ```java User user = new User(); user.setName("John"); user.setAge(30); ``` 2. 将 User 对象添加到一个 map 中,并将变量名设置为 user。 ```java Map<String, Object> variables = new HashMap<>(); variables.put("user", user); ``` 3. 使用 AbstractFlowableVariableExpressionFunction 获取 User 对象的 name 属性。 ```java AbstractFlowableVariableExpressionFunction function = new AbstractFlowableVariableExpressionFunction() { @Override public String getVariableName() { return "property"; } @Override public Object getValue(Map<String, Object> variables, String varName) { String[] varNameSplit = varName.split("\\."); if (varNameSplit.length != 2) { throw new RuntimeException("Invalid property expression: " + varName); } Object object = variables.get(varNameSplit[0]); try { Field field = object.getClass().getDeclaredField(varNameSplit[1]); field.setAccessible(true); return field.get(object); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException("Unable to get property value: " + varName, e); } } }; Object name = function.evaluate(variables, "user.name"); System.out.println(name); // Output: John ``` 在上述示例中,我们使用了一个匿名的 AbstractFlowableVariableExpressionFunction 类来实现获取对象的某个属性的逻辑。我们首先将 User 对象添加到 map 中,然后使用 evaluate 方法获取 User 对象的 name 属性。注意,我们使用了 user.name 的方式来指定要获取属性,其中 user 是变量名,name 是属性名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值