2012-04-27 102 views
11

关于这个话题有很多问题,但我有一个稍微改变了它的版本。确定一个类是否实现了一个非常特定的接口

我们有以下代码:

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

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

现在,故事的扭曲:方法Implements_IFoo应该只在类型,而不是实现的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)) { ... })。我们正在使用现在特定代码的接口替换类。此外,为了以防万一 - 我将此检查作为布尔标志实施,所以此问题纯粹是假设性的。

+1

我真的很好奇,为什么你需要这种内省的第一位。机会是你的设计是错误的。 – tdammers 2012-04-27 13:38:15

+0

请在下次发表评论前仔细阅读问题 - 我已经解释过这是一个假设问题;) – Jefim 2012-04-27 16:39:22

回答

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是否存在于除类型的确切级别以外的任何级别。

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

不过,正如其他人已经说过的,如果这真的是你的需求,那么你的设计可能会有问题。 (编辑:只注意到你的问题纯属假设然后它的罚款,当然:))。

+0

谢谢,这正是我的意思。标记你的答案是正确的,因为这是第一个正确答案。 :) – Jefim 2012-04-27 17:53:48

0

您是否尝试过使用关键字is

顺便说一句,如果你有一个合乎逻辑的情况,一些类需要是某种基类的类型而不是某个继承者,那么这可能是错误的OO设计,可能违反了Liskov substitution principle

+1

在“类型”对象上? – mellamokb 2012-04-27 13:36:11

+0

再一次,'is'没有帮助,因为它会为expr返回'true'。 'Bar is IFoo'(当Bar实现IFoo'到'IBar'时,所需输出为'false')。如果你关心的是彻底阅读这个问题,你就不必费心提及Liskov和OO的设计。关键字:假设/理论。 ;) – Jefim 2012-04-27 16:50:54

3

有关如何实现这些示例,请参见以下网站:

C# is keyword usage

从本质上讲,你可以用“是”关键字来确定对象是否存在于一个类类型,因为它的类继承堆栈的一部分。

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; 
} 
+0

我知道'is'关键字并没有解决问题。请参阅我的问题部分的例子。请注意,IBar来自IFoo。因此Bar也通过IBar实现它。对于expr,'is'将返回true。 '酒吧是IFoo',但那不是理想的结果。 – Jefim 2012-04-27 16:44:26

0

Type类有一个名为GetInterface方法可以使用。

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

它检查整个层次结构中的所有接口,并因此失败了第二个用例'Implements_IFoo(typeof(Bar));' – mellamokb 2012-04-27 13:50:00

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; 
} 
+0

感谢您的答案!这正是我的意思。 – Jefim 2012-04-27 17:30:46

1

这应该做的伎俩:

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

可能有更有效的方式。

+0

我想你的意思是'typeof(IFoo).IsAssignableFrom(t)'而不是't是IFoo',但是,是的,这是东西:) – Jefim 2012-04-27 17:10:53

+0

而且为了以防万一 - 代码不检查基类(好吧,那在我的问题中没有明确定义)以及类型没有任何接口的情况(=>'.Any(..)'然后返回false)。 – Jefim 2012-04-27 17:29:24

相关问题