GetProperties()返回接口继承层次结构的所有属性

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (44)

假设以下假设的继承层次结构:

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

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

使用反射并进行以下调用:

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

只会产生接口的属性。IB,也就是“Name

如果我们要对以下代码进行类似的测试,

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“和”Name

是否有一种简单的方法可以像第一个示例那样在继承层次结构中找到接口的所有属性?

提问于
用户回答回答于

我已经将示例代码调整为一个有用的扩展方法,它封装了类和接口。它还首先添加了接口属性,我认为这是预期的行为。

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);
}
用户回答回答于

Type.GetInterfaces 返回扁平层次结构,所以不需要递归下降。

使用LINQ可以更简洁地编写整个方法:

public static IEnumerable<PropertyInfo> GetPublicProperties(this Type type)
{
    if (!type.IsInterface)
        return type.GetProperties();

    return (new Type[] { type })
           .Concat(type.GetInterfaces())
           .SelectMany(i => i.GetProperties());
}

扫码关注云+社区