C#中typeof调用GetProperties无返回而GetType可返回的原因及解决方法
问题原因
你遇到的问题本质是泛型参数的类型推断规则导致的:
- 首次调用
GetPropertyKeyValue(home, null, pairs)时,泛型参数T会被推断为你传入的Home实例类型,typeof(T)取到的是正确的Home类元数据,因此可以正常获取属性列表。 - 递归调用时,你传入的第一个参数是
property.GetValue(obj, null)的返回值,这个方法的返回值固定为object类型,因此泛型参数T会被推断为System.Object,typeof(T)实际取到的是基类Object的元数据,本身没有你定义的业务属性,自然返回空集合。
解决方案
你不需要依赖实例来获取属性元数据,上层属性已经包含了下属属性的类型定义,我们可以调整方法逻辑,显式传递要反射的类型,同时兼容实例为null的场景:
using System.Reflection; using System.Collections.Generic; // 对外暴露的泛型入口方法 public void GetPropertyKeyValue<T>(T obj, string prefix, List<ExtractedTerm> pairs) { if (pairs == null) { throw new ArgumentNullException(nameof(pairs)); } // 首次调用传入泛型对应的类型和实例 GetPropertyKeyValueCore(typeof(T), obj, prefix, pairs); } // 内部核心递归方法,显式接收目标类型参数 private void GetPropertyKeyValueCore(Type targetType, object obj, string prefix, List<ExtractedTerm> pairs) { // 从传入的目标类型取属性元数据,和实例是否为null无关 var properties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var property in properties) { // 拼接点分路径的key string key = string.IsNullOrWhiteSpace(prefix) ? property.Name : $"{prefix}.{property.Name}"; Type propertyType = property.PropertyType; // 实例为null时直接赋值null,避免空引用 object value = obj == null ? null : property.GetValue(obj, null); // 判断是否为需要递归的自定义类类型 if (propertyType.IsClass && !propertyType.IsInterface && !propertyType.IsEnum && !propertyType.IsPrimitive && propertyType != typeof(string)) { // 递归时传入当前属性的类型,不需要依赖泛型推断 GetPropertyKeyValueCore(propertyType, value, key, pairs); continue; } pairs.Add(new ExtractedTerm(key, value, propertyType)); } }
调用方式和你原来的写法完全一致,不需要修改调用代码。这个方案的优势:
- 始终通过属性定义的
PropertyType获取元数据,既避免了泛型推断错误,也不需要调用实例的GetType()方法,不会因为实例为null抛出空引用异常 - 即便中间层级的实例为null(比如示例中的
Street属性未赋值),也可以完整生成所有层级的点分路径key,对应值为null,符合你的需求。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

