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

C# 通过反射获取类属性标识名称

JSON序列化的时候,往往前后端的属性名称回不一样,尤其是再调用第三方接口的时候,为了减少这方便的麻烦,一般我们在自定义实体的时候,回使用数据契约(DataContract) 

一旦声明一个类型为DataContract,那么该类型就可以被序列化在服务端和客户端之间传送,如下所示。

复制代码
[DataContract(Name = "People")]
public class Person
{
    [DataMember(Name = "Name")]
    public String UserName { get; set; }

    [DataMember(Name = "Age")]
    public String UserAge { get; set; }
}
复制代码

DataMember(数据成员)有很多属性,这里不一一讨论,主要说一下如何通过属性名获取DataMember的Name属性

一、获取类所有属性的标记名称

复制代码
        /// <summary>
        /// 获取属性标记名称
        /// </summary>
        /// <returns></returns>
        public List<String> GetAttributeSignName()
        {
            var SignNames = new List<String>();
            var MyProperties = typeof(People).GetProperties();
            foreach (var property in MyProperties)
            {
                var attributes = property.GetCustomAttributes(typeof(DataMemberAttribute), true);
                foreach (DataMemberAttribute dma in attributes)
                {
                    SignNames.Add(dma.Name);
                }
            }
            return SignNames;
        }
复制代码

二、获取指定属性名的属性标记名称

复制代码
        /// <summary>
        /// 获取属性标记名称
        /// </summary>
        /// <param name="T">实体类</param>
        /// <param name="SN">属性名</param>
        /// <returns></returns>
        public String GetAttributeSignName(Person T,String SN)
        {
            var SignName = "";
            var Attribute = T.GetType().GetProperties().FirstOrDefault(e => e.Name == SN);
            var Sign = (DataMemberAttribute)Attribute.GetCustomAttributes(typeof(DataMemberAttribute), true)[0];
            SignName  = Sign.Name;
            return SignName;
        }    
复制代码

现实开发中,我们还会经常用到另一种场景

三、属性名是字符串,获取该属性的值

using System.Reflection;  
  
var obj = new Person();  
Response.Write(obj.GetType().GetProperty("UserName").GetValue()) ;

四、通过对象的属性,获取对象的名称字符串

复制代码
using System.Linq.Expressions;  
public string GetPropertyName<T>(Expression<Func<T,object>> expr)  
{  
  var rtn = "";  
  if (expr.Body is UnaryExpression)  
  {  
    rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.Name;  
  }  
  else if (expr.Body is MemberExpression)  
  {  
    rtn = ((MemberExpression)expr.Body).Member.Name;  
  }  
  else if (expr.Body is ParameterExpression)  
  {  
    rtn = ((ParameterExpression)expr.Body).Type.Name;  
  }  
    return rtn;  
}  
     
Response.Write(GetPropertyName<Person>(p=>p.UserName)) ; //输出的是 "UserName" 八字母
Response.Write(GetPropertyName<Person>(p=>p.UserAge)) ; //输出的是 "UserAge" 七个字母
Response.Write(GetPropertyName<Person>(p=>p)) ; //输出的是 "Person" 六个字母
复制代码

五、通过对象的属性,获取对象的属性标记名称

复制代码
using System.Linq.Expressions;  

public string GetPropertyAttributeName<T>(Expression<Func<T, object>> expr)
{
  var rtn = "";
  if (expr.Body is UnaryExpression)
  {
    rtn = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.CustomAttributes.FirstOrDefault().NamedArguments.FirstOrDefault().TypedValue.Value.ToString();
  }
  else if (expr.Body is MemberExpression)
  {
    rtn = ((MemberExpression)expr.Body).Member.CustomAttributes.FirstOrDefault().NamedArguments.FirstOrDefault().TypedValue.Value.ToString();
  }
  else if (expr.Body is ParameterExpression)
  {
    rtn = ((ParameterExpression)expr.Body).Type.CustomAttributes.FirstOrDefault().NamedArguments.FirstOrDefault().TypedValue.Value.ToString();
  }
  return rtn;
}

Response.Write(GetPropertyAttributeName<Person>(p=>p.UserName)) ; //输出的是 "Name" 四字母
Response.Write(GetPropertyAttributeName<Person>(p=>p.UserAge)) ; //输出的是 "Age" 三个字母
Response.Write(GetPropertyAttributeName<Person>(p=>p)) ; //输出的是 "People" 五个字母
复制代码

注意: 这里的方法,只是为了测试,还应该考虑异常,容错等问题。比如:

这里需要考虑Property是否有Attribute及多Attributes,以及每个Attribute的是否有值或多个属性值等问题

常使用的还有要考虑从 NamedArguments 和 ConstructorArguments 获取参数及值的问题。

 

另外,这里也可以考虑使用switch的模式匹配来实现

        public string GetPropertyAttributeName2<T>(Expression<Func<T, object>> expr)
        {
            var rtn = "";
            switch (expr.Body)
            {
                case MemberExpression a:
                    rtn = ((MemberExpression)expr.Body).Member.CustomAttributes.FirstOrDefault().NamedArguments.FirstOrDefault().
                        TypedValue.Value.ToString();
                    break;
                case UnaryExpression a:
                    var attr = ((MemberExpression)((UnaryExpression)expr.Body).Operand).Member.CustomAttributes.FirstOrDefault();
                    var attrAttr = attr?.NamedArguments.FirstOrDefault();
                    rtn = attrAttr?.TypedValue.Value.ToString();
                    break;
                case ParameterExpression a:
                    rtn = ((ParameterExpression)expr.Body).Type.CustomAttributes.FirstOrDefault().NamedArguments.FirstOrDefault().
                        TypedValue.Value.ToString();
                    break;
                default:
                    break;
            }
            return rtn;
        }

 

 

出处:https://www.cnblogs.com/hopedilei/p/10429729.html

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

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

posted on 2022-12-01 11:22  jack_Meng  阅读(1625)  评论(0编辑  收藏  举报

导航