You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过反射获取含私有Setter的类属性遇到的异常问题

反射获取带私有Setter属性时的继承类问题

我尝试通过反射获取类中所有带有私有Setter的属性,过程看似简单却遇到了一个异常但符合CLR行为逻辑的问题。

我的初始实现

我写了这样一个Type扩展方法:

public static IEnumerable<PropertyInfo> InstanceProperties(this Type type) {
    List<PropertyInfo> results = new();
    var allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (var property in allProperties) {
        var setMethod = property.GetSetMethod(true);
        if (setMethod != null && setMethod.IsPrivate) {
            results.Add(property);
        }
    }
    return results;
}

测试用类与测试代码

为了验证逻辑,我创建了简单的继承类:

public class BaseClass {
    public string Name { get; private set; }
    public BaseClass(string name) {
        Name = name;
    }
}

public class DerivedClass : BaseClass {
    public string Description { get; private set; }
    public DerivedClass(string name, string description) : base(name) {
        Description = description;
    }
}

对应的测试代码:

[Fact]
public void InstanceProperties_WithBaseType_ReturnsAllProperties() {
    // Arrange
    Type baseEntityType = typeof(BaseClass);
    // Act
    var result = baseEntityType.InstanceProperties();
    // Assert
    result.Should().NotBeNullOrEmpty();
    result.Count().Should().Be(1);
}

[Fact]
public void InstanceProperties_WithDerivedType_ReturnsAllProperties() {
    // Arrange
    Type baseEntityType = typeof(DerivedClass);
    // Act
    var result = baseEntityType.InstanceProperties();
    // Assert
    result.Should().NotBeNullOrEmpty();
    result.Count().Should().Be(2);
}

问题现象

第一个测试(针对BaseClass)正常通过,但第二个测试(针对DerivedClass)失败了。具体表现为:
type.GetProperties(BindingFlags.Public | BindingFlags.Instance)确实返回了两个属性(Name和Description),但基类的Name属性调用GetSetMethod(true)却返回null——这和直接针对BaseClass获取时能找到私有Setter的情况完全相反。

请问该如何解释这一行为,以及如何解决?


补充说明

根据反馈,进一步明确我的最终需求:要构造的对象类型需满足:

  • 可直接继承自知名基类(如Entity),该基类有一个带私有Setter的Guid类型唯一实例属性
  • 可继承自抽象基类,而该抽象基类又继承自Entity
  • 所有实例属性均带有私有Setter
  • 所有类都有一个名为Create的公共静态工厂方法,不同类的方法参数不同

另外我还想了解,Entity Framework是如何处理这种构造方式的,因为它会使用私有无参构造函数创建对象实例。


最终解决方案

我最终编写了一个解决方案,和Jamiec、Gert Arnold提出的方案非常相似,分享出来供大家参考!感谢各位的帮助!

public static IEnumerable<PropertyInfo> InstanceProperties(this Type type) {
    List<PropertyInfo> results = new();
    Type? leafType = type;
    while (leafType != null) {
        var allProperties = leafType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var property in allProperties) {
            var accessors = property
                .GetAccessors(true)
                .Where(a => a.ReturnType == typeof(void) && a.IsPrivate)
                .ToArray();
            foreach (var accessor in accessors) {
                results.Add(property);
            }
        }
        leafType = leafType.BaseType;
    }
    return results;
}

内容的提问来源于stack exchange,提问作者Mammt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:23:13