当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《GetProperties()返回接口继承层次结构的所有属性》经验,为你挑选了3个好方法。

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

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" 的对象数组.

有没有一种简单的方法来查找接口的继承层次结构中的所有属性,如第一个示例中所示?



1> mythz..:

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

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

        var considered = new List();
        var queue = new Queue();
        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);
}


由于GetInterfaces()已经返回由类型实现的所有接口,因此不需要递归或队列.正如马克所说,没有等级制度,那么为什么我们要对任何东西进行"递归"呢?
@FrankyHollywood这就是你不使用`GetProperties`的原因.您在起始类型上使用`GetInterfaces`,它将返回所有接口的展平列表,并在每个接口上执行`GetProperties`.不需要递归.接口中没有继承或基类型.

2> Douglas..:

Type.GetInterfaces 返回展平的层次结构,因此不需要递归下降.

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

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

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


这肯定是正确的答案!不需要笨重的递归.

3> Marc Gravell..:

接口层次结构是一种痛苦 - 它们并不真正"继承",因为你可以拥有多个"父母"(因为想要更好的术语).

"扁平化"(再次,不是正确的术语)层次结构可能涉及检查接口实现的所有接口并从那里开始工作......

interface ILow { void Low();}
interface IFoo : ILow { void Foo();}
interface IBar { void Bar();}
interface ITest : IFoo, IBar { void Test();}

static class Program
{
    static void Main()
    {
        List considered = new List();
        Queue queue = new Queue();
        considered.Add(typeof(ITest));
        queue.Enqueue(typeof(ITest));
        while (queue.Count > 0)
        {
            Type type = queue.Dequeue();
            Console.WriteLine("Considering " + type.Name);
            foreach (Type tmp in type.GetInterfaces())
            {
                if (!considered.Contains(tmp))
                {
                    considered.Add(tmp);
                    queue.Enqueue(tmp);
                }
            }
            foreach (var member in type.GetMembers())
            {
                Console.WriteLine(member.Name);
            }
        }
    }
}


我不同意.尽管对Marc充满敬意,但这个答案也没有意识到GetInterfaces()已经返回了一个类型的所有实现接口.正因为没有"层次结构",所以不需要递归或队列.
推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有