GetProperties中()为接口继承层次返回所有属性属性、层次、接口、GetProperties

2023-09-02 20:43:34 作者:有梦就别怕痛

假设下面的假设继承层次:

Assuming the following hypothetical inheritance hierarchy:

public interface IA
{
  int ID { get; set; }
}

public interface IB : IA
{
  string Name { get; set; }
}

使用反射,使下面的调用:

Using reflection and making the following call:

typeof(IB).GetProperties(BindingFlags.Public | BindingFlags.Instance)

只会产生接口的属性 IB ,这是名称

如果我们做了一个类似的测试以下code,

If we were to do a similar test on the following code,

public abstract class A
{
  public int ID { get; set; }
}

public class B : A
{
  public string Name { get; set; }
}

呼叫的typeof(B).GetProperties(BindingFlags.Public | BindingFlags.Instance)返回的PropertyInfo数组对象为 ID 名称

有没有一种简单的方法来找到接口的继承层次结构的所有属性,在第一个例子?

Is there an easy way to find all the properties in the inheritance hierarchy for interfaces as in the first example?

推荐答案

我已经调整@Marc砾石的例子code到有用的扩展方法封装类和接口。它还添加的接口属性第一,我相信是预期的行为。

I've tweaked @Marc Gravel's example code into a useful extension method encapsulates both classes and interfaces. It also add's the interface properties first which I believe is the expected behaviour.

public static PropertyInfo[] GetPublicProperties(this Type type)
{
    if (type.IsInterface)
    {
        var propertyInfos = new List<PropertyInfo>();

        var considered = new List<Type>();
        var queue = new Queue<Type>();
        considered.Add(type);
        queue.Enqueue(type);
        while (queue.Count > 0)
        {
            var subType = queue.Dequeue();
            foreach (var subInterface in subType.GetInterfaces())
            {
                if (considered.Contains(subInterface)) continue;

                considered.Add(subInterface);
                queue.Enqueue(subInterface);
            }

            var typeProperties = subType.GetProperties(
                BindingFlags.FlattenHierarchy 
                | BindingFlags.Public 
                | BindingFlags.Instance);

            var newPropertyInfos = typeProperties
                .Where(x => !propertyInfos.Contains(x));

            propertyInfos.InsertRange(0, newPropertyInfos);
        }

        return propertyInfos.ToArray();
    }

    return type.GetProperties(BindingFlags.FlattenHierarchy
        | BindingFlags.Public | BindingFlags.Instance);
}