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
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/16940895.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2022-12-01 11:22 jack_Meng 阅读(1625) 评论(0) 编辑 收藏 举报