确定类是否实现了非常特定的接口

时间:2012-04-27 13:29:15

标签: c# inheritance reflection interface

关于这个主题有很多问题,但我的版本稍有改动。

我们有以下代码:

interface IFoo { }
interface IBar : IFoo { }
class Foo : IFoo { }
class Bar : IBar { }

bool Implements_IFoo(Type type) { /* ??? */ }

现在,故事的转折:方法Implements_IFoo只应在Type仅实现IFoo而不是从IFoo派生的任何接口时返回true。这里举例说明这种方法的一些例子:

Implements_IFoo(typeof(Foo)); // Should return true

Implements_IFoo(typeof(Bar)); // Should return false as Bar type 
                              // implements an interface derived from IFoo

请注意,可能有很多来自IFoo的接口,您不一定知道它们的存在。

显而易见的方法是通过反射找到从IFoo派生的所有接口,然后只检查typeof(Bar).GetInterfaces()就是那里的任何一个。但我想知道是否有人能提出更优雅的解决方案。

PS问题源自我发现的一些代码,这些代码使用了对类(if(obj.GetType() == typeof(BaseClass)) { ... })的检查。我们正在用特定代码的接口替换类。另外,以防万一 - 我将此检查作为布尔标志实现,所以这个问题纯粹是假设的。

6 个答案:

答案 0 :(得分:9)

我试过,因为它听起来很有趣,这适用于你的例子:

bool ImplementsIFooDirectly(Type t) {
    if (t.BaseType != null && ImplementsIFooDirectly(t.BaseType)) { 
        return false; 
    }
    foreach (var intf in t.GetInterfaces()) {
        if (ImplementsIFooDirectly(intf)) { 
            return false;
        }
    }
    return t.GetInterfaces().Any(i => i == typeof(IFoo));
}

结果:

ImplementsIFooDirectly(typeof(IFoo)); // false
ImplementsIFooDirectly(typeof(Bar)); // false
ImplementsIFooDirectly(typeof(Foo)); // true
ImplementsIFooDirectly(typeof(IBar)); // true

它不会查找从IFoo派生的所有接口,它只是沿着继承/接口实现链向上移动,看看IFoo是否存在于除类型的确切级别之外的任何级别

它还检测接口是否通过基类型继承。不确定这是不是你想要的。

尽管如此,正如其他人已经说过的那样,如果您真的需要这样做,那么您的设计可能会遇到问题。 (编辑:刚刚注意到你的问题纯粹是假设的。那当然没问题)))

答案 1 :(得分:3)

有关如何实施此示例的示例,请参阅以下网站;

C# is keyword usage

基本上你可以使用'is'关键字来确定对象是否作为类继承栈的一部分驻留在类类型中。

class Director  : Owner { }
class Developer : Employee { }
..
var dave = new Developer();
var steve = new Director();
var isEmployee = dave is Employee; // true
var isAlsoEmploye = steve is Employee; // false

符合您的示例功能:

bool Implements_Type(object instance, Type type) { 
return instance is type;
}

答案 2 :(得分:2)

static bool Implements_IFoo(Type type)
{
  if (typeof(IFoo).IsAssignableFrom(type.BaseType))
    return false;

  var barInterfaces = type.GetInterfaces()
    .Where(iface => typeof(IFoo).IsAssignableFrom(iface))
    .ToArray();

  return barInterfaces.Length > 0 
     && barInterfaces.Length == barInterfaces.Count(iface => iface == typeof(IFoo));
}
static bool Implements_IFoo_Optimized(Type type)
{
  if (typeof(IFoo).IsAssignableFrom(type.BaseType))
    return false;

  return type.GetInterfaces()
    .Where(iface => typeof(IFoo).IsAssignableFrom(iface))
    .Count() == 1;
}

答案 3 :(得分:1)

这应该可以解决问题:

 public bool ImplementsIFooOnly(Type type)
 {
     return !type.GetInterfaces().Any(t => 
              { 
                   return t is IFoo && !t.Equals(typeof(IFoo)); 
              });
 }

可能有更有效的方法。

答案 4 :(得分:0)

您是否尝试使用关键字is

一般来说,顺便提一下,如果你有一个逻辑情况,某些类需要属于某个基类的类型但不是某个继承者的类型,那么可能是错误的OO设计,可能违反Liskov substitution principle。 / p>

答案 5 :(得分:0)

Type类有一个名为GetInterface的方法,你可以使用它。

    bool Implements_IFoo(Type t)
    {
        return t.GetInterface(typeof(IFoo).Name) != null;
    }