【问题标题】:Get all c# Types that implements an interface first but no derived classes获取所有先实现接口但没有派生类的c#类型
【发布时间】:2014-07-07 06:12:10
【问题描述】:

与Getting all types that implement an interface 相关的我们可以很容易地获取Assembly 中实现特定接口的所有Type。

例子:

interface IFace
{
}

class Face : IFace
{
}

class TwoFace : Face
{
}

对于这个结构,我们将通过反射找到 both 类,即所有从第一个实现派生的类,使用

GetTypes().Where(
  type => type.GetInterfaces().Contains(typeof(IFace))
)

所以问题是:如何将结果限制在最初实现接口的基类中?! 在这个例子中:只有类类型 Face 是相关的。

【问题讨论】:

  • 注意:迭代所有找到的类/类型,检查一个是否派生自另一个似乎不切实际,对我来说也不是性能
  • 这是使用反射的限制。接口不知道哪些类实现了它,因此如果不迭代所有内容,您就无法获得它们。如果你想要更好的性能,你可能需要 Roslyn。
  • @childno.de 一旦你已经迭代了程序集中的所有类型,它不会对简单地检查 thm 的继承产生任何额外的性能影响
  • 你可以通过让不需要的类另外实现一些IFaceFake 接口来欺骗它。
  • @childno.de:你有证据认为它不切实际吗?猜测性能几乎从来都不是一个好主意。

标签: c# reflection


【解决方案1】:

首先,我会使用Type.IsAssignableFrom 而不是GetInterfaces,但是您需要做的就是排除其父类型已经在集合中的类型:

var allClasses = types.Where(type => typeof(IFace).IsAssignableFrom(type))
                      .ToList(); // Or use a HashSet, for better Contains perf.
var firstImplementations = allClasses
      .Except(allClasses.Where(t => allClasses.Contains(t.BaseType)));

或如 cmets 中所述,等效地:

var firstImplementations = allClasses.Where(t => !allClasses.Contains(t.BaseType));

请注意,这不会返回一个派生自实现接口的类的类,而是重新实现它。

【讨论】:

  • 为什么不只是allClasses.Where(t => !allClasses.Contains(t.BaseType))?
  • @BenAaronson:Except 通常效率更高,仅此而已。但是,是的,它们基本上是等价的。
  • 是吗?感觉就像它想要一个自己的问题!
  • @BenAaronson:不是真的 - 只是阅读msmvps.com/blogs/jon_skeet/archive/2010/12/30/…(在这种情况下,实际上它可能不会更有效。我想我没有喝足够的咖啡。)
  • 好的,到目前为止谢谢。似乎在内部 linq 表达式中再次使用受限 allClasses 时,它遇到了 StackOverflow。使用外部 types 进行 Contains(baseType) 检查工作正常,即使它再次迭代整个程序集类型列表;(跨度>
猜你喜欢
  • 1970-01-01
  • 2010-09-06
  • 1970-01-01
  • 2015-11-22
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
相关资源
最近更新 更多