【问题标题】:When enumerating a type's interfaces how do I get only those that are directly inherited?枚举类型的接口时,如何仅获取直接继承的接口?
【发布时间】:2009-02-11 15:48:38
【问题描述】:

我不确定这里的确切术语。基本上,如果我有这样的模型:

class Student : IDoSchool {}
class Freshman : Student {}
interface IDoSchool {}

什么代码会告诉我 Freshman 不直接实现任何接口而 Student 直接实现 IDoSchool?

换句话说(忽略不好的术语)我想要这样的东西:

typeof(Freshman).GetInterfaces(BindingFlags.DeclaredOnly); // nothing
typeof(Student).GetInterfaces(BindingFlags.DeclaredOnly); // IDoSchool

想法?

【问题讨论】:

  • 在你的例子中,新生应该是学生的子类吗?

标签: c# .net reflection


【解决方案1】:

我怀疑接口的语义与您要执行的操作不一致。

接口只是说一个类必须实现一个成员列表。该类继承了接口,但子类仍然有责任实现它从父类继承的接口。大多数情况下,父级已经提供了实现,因此我们倾向于将接口实现视为与继承相同,但实际上它们是完全不同的概念。

在您的情况下,您能做的最好的事情是使用 GetInterfaceMap() 检索接口映射,并确保接口的每个成员的所有实现都来自父级,而不是来自子级。这是你能做的最好的事情,但它仍然不能完全按照你想做的事情做。

另外,在您的情况下是否可以使用完全抽象的类而不是接口?你不能做多重继承,但也许你所有的规则都暗示了一个非常线性的继承?

【讨论】:

  • 我正在开发 .net 验证框架。可以配置规则的方法之一是通过属性。到目前为止,支持能够为接口赋予属性并将这些规则应用于实现该接口的类型。我没有写原始支持,我怀疑(续)
  • 它可能无法按预期工作。我想重写此功能,以便更清楚地支持哪些场景。除了这个问题,我已经很好地处理了类型层次结构。由于 GetInterfaces() 将返回 IDoSchool (cont),因此 IDoSchool 上的上述模型和属性将被找到两次
  • 两种类型。因此,当只应应用一条规则时,我们最终将两条规则应用于新生。如果不可能,我不反对放弃对属性接口的支持(不确定它是否有意义)我只是不想在功能上退一步。
  • 这很奇怪,因为在我的测试中,GetInterfaces 只返回一个接口,即使使用 orsogufo 代码也是如此。据我了解,您的界面将具有一个属性,并且您希望父类继承 attr 而不是子类?如果是这样,我很害怕没有开箱即用的解决方案。
  • 实现接口是想要共享相同语言的类之间的契约,而不是实现者和接口之间的继承关系。接口不应该被视为一个完全抽象的类,它们是不一样的。我更新了答案以涵盖新的解决方案
【解决方案2】:

很抱歉将其发布为答案,这实际上更多是一种想法和建议,但它不适合评论...

如果遇到以下情况怎么办:

interface IA{
    void foo();
}
class CA : IA{
    public void foo(){
        Console.Writeline("Class A");
    }
}
class CB : CA, IA{
    public new void foo(){
        Console.Writeline("Class B");
    }
}

我猜 CB 应该在“直接实现的接口”中返回 IA,但是如果您将 CB 与 CA 进行比较,您会发现它们实现了相同的接口,因此查找差异的方法不起作用。
在疯狂寻找解决方案之前,您是否尝试过查看 MSIL 或从 Reflector 反编译的代码,看看这是否可行?

【讨论】:

    【解决方案3】:
     typeof("the object").GetInterfaces().Count==0
    

    【讨论】:

      【解决方案4】:

      只是一个想法......

      你可以获取类的接口,以及基类的接口。 然后得到差异。

      编辑:

      我已经检查了这个想法,工作正常:

      public static Type[] GetDirectInterfaces(Type type)
      {
          if (type.BaseType == null)
              return type.GetInterfaces();
          Type[] BaseInterfaces = type.BaseType.GetInterfaces();
          Type[] ThisInferfaces = type.GetInterfaces();
          return ThisInferfaces.Except(BaseInterfaces).ToArray();
      }
      

      如果接口数量巨大且执行时间很关键,您可以创建一个单独的带有字典的静态类来缓存结果。

      【讨论】:

      • 如果层次结构很深,我可以看到这很痛苦。我必须得到整个图表,找到最高点,走下去直到我看到一个界面,然后从那个点开始忽略那个界面。我希望有一种更“内置”的方式来做到这一点。如果我对这个过程不感兴趣,你能举个例子吗?
      • 这行不通,因为子类也可以显式实现接口
      • 我们可以查看成员是否显式实现了接口。那么,如果我们假设显式接口将被忽略,这可能吗?
      猜你喜欢
      • 2011-01-31
      • 1970-01-01
      • 2019-11-16
      • 2020-02-23
      • 2022-01-04
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      相关资源
      最近更新 更多