首页 > 编程语言 >C#通过 Expression 表达式获取、设置属性名称、属性值

C#通过 Expression 表达式获取、设置属性名称、属性值

时间:2022-12-01 11:34:30浏览次数:45  
标签:body obj C# param var Expression 属性

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
请按任意键继续. . .

 

 

出处:https://blog.csdn.net/sweety820/article/details/39203087

=======================================================================================

C#通过表达式获取属性名称,设置、获取属性值 

转自 // https://blog.csdn.net/sweety820/article/details/39203087
参考 // https://stackoverflow.com/questions/32146571/expression-of-type-system-int64-cannot-be-used-for-return-type-system-object?noredirect=1&lq=1

代码如下:

    /// <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));
 
            // 原有的,非string类型会报转换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();
 
            //转成真实类型,防止Dynamic类型转换成object
            Expression<Func<T, object>> result = Expression.Lambda<Func<T, object>>(Expression.Convert(Expression.Property(param_obj, p), typeof(object)), param_obj);
            var getValue = result.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);
            }
        }
 
        /// <summary>
        /// 获取类的属性名称
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="source"></param>
        /// <param name="propery"></param>
        /// <returns></returns>
        public static string GetPropName<TSource, TProperty>(this TSource source,
            Expression<Func<TSource, TProperty>> propery) where TSource : class
        {
            var body = propery.Body.ToString();
            return body.Substring(body.LastIndexOf(".") + 1);
        }
 
        public static PropertyInfo GetPropertyInfo<TSource, TProperty>(
        Expression<Func<TSource, TProperty>> propertyLambda)
        {
            Type type = typeof(TSource);
 
            MemberExpression member = propertyLambda.Body as MemberExpression;
            if (member == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a method, not a property.",
                    propertyLambda.ToString()));
 
            PropertyInfo propInfo = member.Member as PropertyInfo;
            if (propInfo == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a field, not a property.",
                    propertyLambda.ToString()));
 
            if (type != propInfo.ReflectedType &&
                !type.IsSubclassOf(propInfo.ReflectedType))
                throw new ArgumentException(string.Format(
                    "Expresion '{0}' refers to a property that is not from type {1}.",
                    propertyLambda.ToString(),
                    type));
 
            return propInfo;
        }
 
        /// <summary>
        /// 获取类的属性信息
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyLambda"></param>
        /// <returns></returns>
        public static PropertyInfo GetPropertyInfo<TSource, TProperty>(this TSource source,
            Expression<Func<TSource, TProperty>> propertyLambda) where TSource : class
        {
            return GetPropertyInfo(propertyLambda);
        }
 
        /// <summary>
        /// 获取类的属性名称 
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="source"></param>
        /// <param name="propertyLambda"></param>
        /// <returns></returns>
        public static string NameOfProperty<TSource, TProperty>(this TSource source,
            Expression<Func<TSource, TProperty>> propertyLambda) where TSource : class
        {
            PropertyInfo prodInfo = GetPropertyInfo(propertyLambda);
            return prodInfo.Name;
        }
    }

 

 

出处:https://blog.csdn.net/XinShun/article/details/88978238

标签:body,obj,C#,param,var,Expression,属性
From: https://www.cnblogs.com/mq0036/p/16940895.html

相关文章

  • RabbitMQ 3.7.18安装延时插件rabbitmq-delayed-message-exchange后启动报错
    环境:安装请参考:https://blog.csdn.net/qq_37487520/article/details/126079651https://www.cnblogs.com/myifb/articles/16638251.html启用插件时,不用写插件版本号:r......
  • js 对象属性过滤方法
    有时候需要剔除少数属性,留下大多数。类似于TS的omit例子:letperson={name:"jackchen",age:54,address:'hongkong'}let{name,...xiaohong}=personcons......
  • Cron表达式速查,1张表记清楚
    Cron表达式是一个字符串,定义时间规则,由6或7个时间域组成,空格分隔。1张表整理清楚含义和规则,并举例常用表达式,放手边速查。Cron表达式时间域序号含义取值范围特殊字......
  • AC 自动机
    AC自动机是更高维的kmp。构造方法感觉更像是运用了dp的思想,先对所有模式串建立一棵Trie树,然后考虑某个节点\(x\),有个\(w\)的后缀,考虑如何去求它的fail值。于是......
  • 使用编译器aarch64-xilinx-linux-gcc,导致uboot编译出现错误“aarch64-xilinx-linux-ld
    KV260PetaLinuxBSP的environment-setup-cortexa72-cortexa53-xilinx-linux会导入aarch64-xilinx-linux系列工具,并设置CROSS_COMPILE为aarch64-xilinx-linux-。因此使用......
  • Oracle中ALTER TABLE的五种用法(四、五)
    首发微信公众号:SQL数据库运维原文链接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1&sn=450e9e94fa709b5eeff0de371c62072b&chksm=ea37536cdd......
  • list、dict和set的综合应用:排课系统(4)
    上回说到,我们成功的实现了排课算法并且生成了课表,这次我们就尝试在首页显示课表,并且实现调用排课的认证。显示课表显示课表非常的简单,在视图中返回的context字典中只有一......
  • list 和 dict 的复制
    我们都知道,Python中有两种可变的数据类型:list和dict。这两种数据类型对应的实例也有很多方法可以对自身进行修改,需要注意的是,这里调用修改相关的方法的时候不是返回修改......
  • 瓴羊Quick BI数据大屏,为企业提供数据可视化服务
    企业在运营管理过程中会产生海量数据,能否对这些数据快速收集并充分挖掘其内在价值,指导企业做出有利于发展的经营决策,是新时期推动企业实现可持续发展的重要前提。若无法合......
  • list、dict和set的综合应用:排课系统(2)
    差一点我们就擦肩而过了有趣有用有态度上回说到,我们主要实现了排课系统的后台数据的定义以及每个数据对象之间的关系,这一次我们就来批量增加一些数据,为了给后面的排课算法进......