.NET Core中如何通过变量名动态访问及赋值类属性?
没问题!在C#里要实现这种通过字符串动态访问、设置对象属性的需求,我们一般用**反射(Reflection)**来搞定,下面给你一步步拆解具体实现:
一、动态获取属性值
首先我们可以借助System.Reflection命名空间里的PropertyInfo类来实现。先看完整的代码示例:
using System.Reflection; public class Student { public string Name { get; set; } public int Age { get; set; } } // 封装一个通用的动态获取属性值方法 public static object GetPropertyValue(object obj, string propertyName) { // 获取目标对象的类型 Type objType = obj.GetType(); // 查找指定的公共实例属性(这里的BindingFlags很重要,确保能正确找到属性) PropertyInfo property = objType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance); if (property == null) { throw new ArgumentException($"找不到属性:{propertyName}(类型:{objType.Name})"); } // 获取并返回属性值 return property.GetValue(obj); } // 使用示例 Student s = new Student { Name = "Alice", Age = 20 }; string targetProperty = "Age"; var ageValue = GetPropertyValue(s, targetProperty); // 返回20(类型为object,可按需强转:(int)ageValue)
这里要注意:
- 必须引用
System.Reflection命名空间; BindingFlags.Public | BindingFlags.Instance是为了明确查找公共的实例属性,如果你的属性是非公共的,需要调整绑定标志;- 返回值是
object类型,实际使用时可以根据属性的真实类型进行强转。
二、动态设置属性值
同理,我们可以用PropertyInfo.SetValue()方法来实现动态赋值,甚至可以额外处理类型转换的场景(比如把字符串转成int):
// 封装通用的动态设置属性值方法 public static void SetPropertyValue(object obj, string propertyName, object value) { Type objType = obj.GetType(); PropertyInfo property = objType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance); if (property == null) { throw new ArgumentException($"找不到属性:{propertyName}(类型:{objType.Name})"); } // 可选:自动转换值的类型,适配属性类型 try { value = Convert.ChangeType(value, property.PropertyType); } catch (InvalidCastException ex) { throw new ArgumentException($"无法将值 {value} 转换为属性 {propertyName} 的类型 {property.PropertyType}", ex); } // 设置属性值 property.SetValue(obj, value); } // 使用示例 Student s = new Student { Name = "Bob", Age = 25 }; string targetProperty = "Age"; SetPropertyValue(s, targetProperty, 35); // 此时s.Age变为35 // 也支持跨类型转换(比如字符串转int) SetPropertyValue(s, targetProperty, "40"); // s.Age会被设置为40
这个方法里加了类型转换的逻辑,能处理一些常见的类型不匹配场景,比如用户传入字符串类型的数字,自动转成int赋值给Age属性。
三、性能优化小技巧(可选)
反射虽然好用,但如果是高频调用的场景,可能会有一定的性能开销。这时候可以用**表达式树(Expression Tree)**缓存获取/设置属性的委托,性能接近直接调用属性:
using System.Linq.Expressions; // 缓存获取属性的委托 private static readonly Dictionary<(Type, string), Func<object, object>> _getterCache = new Dictionary<(Type, string), Func<object, object>>(); public static object GetPropertyValueFast(object obj, string propertyName) { var cacheKey = (obj.GetType(), propertyName); // 先从缓存取,没有则编译表达式树 if (!_getterCache.TryGetValue(cacheKey, out var getter)) { var param = Expression.Parameter(typeof(object), "obj"); var castObj = Expression.Convert(param, cacheKey.Item1); var property = Expression.Property(castObj, propertyName); var castResult = Expression.Convert(property, typeof(object)); getter = Expression.Lambda<Func<object, object>>(castResult, param).Compile(); _getterCache[cacheKey] = getter; } return getter(obj); }
设置属性的委托缓存逻辑类似,这里就不重复写了。这种方式第一次调用会编译表达式,之后直接调用缓存的委托,性能提升很明显。
内容的提问来源于stack exchange,提问作者Rushikesh Sane
相关产品推荐
相关产品推荐

