检索类型的叶接口

发布于 2024-08-05 15:44:41 字数 1305 浏览 5 评论 0原文

System.Type 类提供了一个 GetInterfaces() 方法“获取由当前类型”。 问题在于“GetInterfaces 方法不会按特定顺序(例如字母顺序或声明顺序)返回接口。您的代码不得依赖于返回接口的顺序,因为该顺序会有所不同”。 然而,就我而言,我需要仅隔离和公开(通过 WCF)接口层次结构的叶接口,即不被该层次结构中的其他接口继承的接口。例如,考虑以下层次结构

interface IA { }
interface IB : IA { }
interface IC : IB { }
interface ID : IB { }
interface IE : IA { }
class Foo : IC, IE {}

Foo 的叶接口是 IC 和 IE,而 GetInterfaces() 将返回所有 5 个接口 (IA..IE)。 还提供了 FindInterfaces() 方法,允许您可以使用您选择的谓词来过滤上述接口。

我当前的实现如下。它是 O(n^2),其中 n 是该类型实现的接口的数量。我想知道是否有一种更优雅和/或更有效的方法来做到这一点。

    private Type[] GetLeafInterfaces(Type type)
    {
        return type.FindInterfaces((candidateIfc, allIfcs) =>
        {
            foreach (Type ifc in (Type[])allIfcs)
            {
                if (candidateIfc != ifc && candidateIfc.IsAssignableFrom(ifc))
                    return false;    
            }
            return true;
        }
        ,type.GetInterfaces());
    }

提前致谢

The System.Type class provides a GetInterfaces() method that "gets all the interfaces implemented or inherited by the current Type".
The problem is that "The GetInterfaces method does not return interfaces in a particular order, such as alphabetical or declaration order. Your code must not depend on the order in which interfaces are returned, because that order varies".
In my case, however, I need to isolate and expose (via WCF) only the leaf interfaces of the interface hierarchy, that is interfaces that are not inherited by other interfaces in that hierarchy. For example, consider the following hierarchy

interface IA { }
interface IB : IA { }
interface IC : IB { }
interface ID : IB { }
interface IE : IA { }
class Foo : IC, IE {}

Foo's leaf interfaces are IC and IE, whereas GetInterfaces() will return all 5 interfaces (IA..IE).
A FindInterfaces() method is also provided, allowing you to filter the aforementioned interfaces using a predicate of your choice.

My current implementation is given below. It is O(n^2) where n is the number of interfaces the type implements. I was wondering if there was a more elgant and/or efficient way of doing it.

    private Type[] GetLeafInterfaces(Type type)
    {
        return type.FindInterfaces((candidateIfc, allIfcs) =>
        {
            foreach (Type ifc in (Type[])allIfcs)
            {
                if (candidateIfc != ifc && candidateIfc.IsAssignableFrom(ifc))
                    return false;    
            }
            return true;
        }
        ,type.GetInterfaces());
    }

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如此安好 2024-08-12 15:44:41

我认为您不会找到简单的解决方案。您的问题是,最终,Foo 实际上实现了所有接口,无论其内部继承层次结构如何。如果您使用 Ildasm 或一些类似的工具检查 Foo,这一点就会变得很明显。考虑以下代码:

interface IFirst { }
interface ISecond : IFirst { }
class Concrete : ISecond { }

生成的 IL 代码(从 Ildasm 转储):

.class private auto ansi beforefieldinit MyNamespace.Concrete
       extends [mscorlib]System.Object
       implements MyNamespace.ISecond,
                  MyNamespace.IFirst
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Concrete::.ctor

} // end of class MyNamespace.Concrete

如您所见,在这个级别上,Concrete 和两个接口之间的关系没有区别。

I don't think you will find a simple solution to this. Your problem is that in the end, Foo actually implements all the interfaces, regardless of their internal inheritance hierarchy. If you examine Foo using Ildasm or some similar tool this becomes evident. Consider the following code:

interface IFirst { }
interface ISecond : IFirst { }
class Concrete : ISecond { }

The resulting IL code (dumped from Ildasm):

.class private auto ansi beforefieldinit MyNamespace.Concrete
       extends [mscorlib]System.Object
       implements MyNamespace.ISecond,
                  MyNamespace.IFirst
{
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Concrete::.ctor

} // end of class MyNamespace.Concrete

As you can see, on this level there is no difference in the relation between Concrete and the two interfaces.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文