通过私有设置器获取类的反射属性

问题描述 投票:0回答:1

我正在尝试获取具有私有设置器的类的所有属性。这看起来很简单,但是我遇到了一种奇怪但可能正常的行为。

这是我实施的解决方案

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);
}

第一次测试成功,第二次测试失败。更具体地说,在第二个测试中,代码 var

allProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
返回两个属性,但基类的属性没有 setter 方法。这与第一个测试不太一致,因为在这种情况下,该属性确实有一个被定义为私有的 set 方法。

对此行为有什么建议/解释吗?

编辑 根据评论的建议,我更好地解释了问题的范围。最终目标是构造具有以下特征的某些类型的对象:

  • 可以是直接从众所周知的基类(例如
    Entity
    )继承的类,这些基类具有带有私有设置器的 Guid 类型的单个唯一实例属性
  • 可以是从抽象基类继承的类,而抽象基类又从
    Entity
  • 继承
  • 所有实例属性都有一个私有设置器
  • 所有类都有一个名为
    Create
    的公共静态工厂方法,当然每个类都有不同的参数

我想了解实体框架如何处理这种构造技术,它使用私有无参数构造函数来创建对象实例。

c# reflection .net-8.0
1个回答
0
投票

这可能就像一些递归一样简单,如果该类型具有基本类型,请将这些属性添加到您的列表中:

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

在这个特定示例中,这给出了您预期的

2
输出,但可能需要一些调整才能满足您的确切期望。

© www.soinside.com 2019 - 2024. All rights reserved.