泛型SQL命令生成代码中通过属性名获取属性值的疑问
嘿,我之前做泛型SQL生成器的时候也碰到过一模一样的嵌套属性取值问题!结合你给出的Question类结构,先补全一下合理的类定义方便举例(假设Answer是关联的内部类或独立类):
[Table("Question")] public class Question { [Column("QuestionID", true)] public int QuestionId { get; set; } [Column("Number")] public string Nr { get; set; } // 假设这是你提到的Answer关联属性 public Answer QuestionAnswer { get; set; } // 如果Answer是Question的内部类 public class Answer { public string Content { get; set; } public int Score { get; set; } } }
接下来给你两个实用的解决方案:
方案1:反射处理嵌套属性(简单易实现)
这种方式适合低频调用场景,直接通过反射拆分属性路径,逐层获取实例/值:
public static object GetNestedPropertyValue(object targetObj, string propertyPath) { if (targetObj == null || string.IsNullOrWhiteSpace(propertyPath)) return null; var propertySegments = propertyPath.Split('.'); var currentInstance = targetObj; foreach (var propName in propertySegments) { if (currentInstance == null) break; var type = currentInstance.GetType(); // 查找公开实例属性,如需支持非公开可调整BindingFlags var property = type.GetProperty(propName, BindingFlags.Public | BindingFlags.Instance); if (property == null) throw new ArgumentException($"找不到属性 {propName},所属类型:{type.FullName}"); currentInstance = property.GetValue(currentInstance); } return currentInstance; }
用法示例
// 获取Answer属性的实例 var answerInstance = GetNestedPropertyValue(myObject, "QuestionAnswer"); // 获取Answer实例中的Content值 var answerContent = GetNestedPropertyValue(myObject, "QuestionAnswer.Content");
方案2:表达式树(高性能高频调用首选)
反射每次调用都要重复查找属性,表达式树可以提前编译成委托,适合频繁调用的场景:
public static Func<T, object> CreateNestedPropertyGetter<T>(string propertyPath) { var param = Expression.Parameter(typeof(T), "target"); Expression expression = param; foreach (var propName in propertyPath.Split('.')) { expression = Expression.Property(expression, propName); } // 值类型需要装箱转换为object if (expression.Type.IsValueType) { expression = Expression.Convert(expression, typeof(object)); } var lambda = Expression.Lambda<Func<T, object>>(expression, param); return lambda.Compile(); }
用法示例
// 提前编译一次,后续重复调用 var answerContentGetter = CreateNestedPropertyGetter<Question>("QuestionAnswer.Content"); // 快速取值 var contentValue = answerContentGetter(myObject);
额外注意点
- 空值处理:如果中间某个属性是
null,反射方案会返回null,你可以根据需求添加空值判断或抛出异常 - 大小写敏感:默认反射是大小写敏感的,如果需要兼容不敏感的场景,可以自己实现属性名的模糊匹配逻辑
- 内部类适配:不管Answer是独立类还是Question的内部类,上述两种方案都能正常工作,只要属性路径正确即可
内容的提问来源于stack exchange,提问作者BlackPhoenix134
相关产品推荐
相关产品推荐

