关于这个主题有很多问题,但我的版本略有改动。
我们有以下代码:
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)) { ... }
)。我们正在用特定代码的接口替换类。另外,以防万一 - 我将此检查作为布尔标志实现,所以这个问题纯粹是假设的。
我试过了,因为它听起来很有趣,这适用于你的例子:
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
存在于除类型的确切级别之外的任何级别。
它还检测接口是否通过基类型继承。不确定这是不是你想要的。
尽管如此,正如其他人已经说过的那样,如果这对您来说真的是一个要求,那么您的设计可能会遇到问题。 (编辑:刚刚注意到你的问题纯粹是假设的。那当然没关系:))
有关如何实施此示例的示例,请参阅以下站点;
C#是关键字用法
本质上,您可以使用'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;
}
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;
}
这应该是诀窍:
public bool ImplementsIFooOnly(Type type)
{
return !type.GetInterfaces().Any(t =>
{
return t is IFoo && !t.Equals(typeof(IFoo));
});
}
可能有更有效的方法。
您是否尝试使用该关键字? is
?
BTW一般来说,如果你有一个逻辑情况,某些类需要是某个基类的类型但不是某个继承者的类型,那么它可能是错误的OO设计,可能违反了 利斯科夫替代原则。
Type类有一个可以使用的名为GetInterface的方法。
bool Implements_IFoo(Type t)
{
return t.GetInterface(typeof(IFoo).Name) != null;
}