如何使用 C# 反射确定类型是否实现接口
C#
中的反射是否提供了一种方法来确定某些给定的 System.Type
类型是否模型了某个接口?
public interface IMyInterface {}
public class MyType : IMyInterface {}
// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);
Does reflection in C#
offer a way to determine if some given System.Type
type models some interface?
public interface IMyInterface {}
public class MyType : IMyInterface {}
// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
我认为这是正确的版本,原因有三个:
IsAssignableFrom 经过多次检查后最终确实调用
获取接口。
没有边界检查。
类型,因此可能比 Equals 方法更安全(即 Contains
调用,最终会使用)。
I think this is the correct release, for three reasons:
IsAssignableFrom eventually after several checks does call
GetInterfaces.
no bounds checks.
Type, so probably is safer than the Equals method (that the Contains
call, will eventually use).
如果您有类型或实例,您可以轻松检查它们是否支持特定接口。
测试对象是否实现某个接口:
测试类型是否实现某个接口:
如果您有一个泛型对象并且想要进行强制转换并检查您强制转换到的接口是否已实现,则代码为:
If you have a type or an instance you can easily check if they support a specific interface.
To test if an object implements a certain interface:
To test if a type implements a certain interface:
If you got a generic object and want to do a cast as well as a check if the interface you cast to is implemented the code is:
我刚刚做了:
我希望我可以说
where I:interface
,但是interface
不是通用参数约束选项。class
是最接近的。用法:
我只是说
Implements
,因为这样更直观。我总是会遇到IsAssignableFrom
翻转的情况。I just did:
I wish I could have said
where I : interface
, butinterface
is not a generic parameter constraint option.class
is as close as it gets.Usage:
I just said
Implements
because that's more intuitive. I always getIsAssignableFrom
flip-flopped.正如其他人已经提到的:
本杰明 2013 年 4 月 10 日 22:21"
好吧,另一种方法是创建一个简短的扩展方法,在某种程度上实现“最常用”的思维方式(并同意这是一个非常小的个人选择,使其成为可能)根据个人喜好稍微“更自然”):
为什么不更通用一点(好吧不确定它是否真的那么有趣,我想我只是再传递一点“语法”糖):
我认为它这样可能会更自然,但这又只是个人意见的问题:
As someone else already mentioned:
Benjamin Apr 10 '13 at 22:21"
Well, another way around is just to create a short extension method that fulfills, to some extent, the "most usual" way of thinking (and agreed this is a very little personal choice to make it slightly "more natural" based on one's preferences):
And why not going a bit more generic (well not sure if it is really that interesting, well I assume I'm just passing another pinch of 'syntaxing' sugar):
I think it might be much more natural that way, but once again just a matter of very personal opinions:
修改 Jeff 的答案以获得最佳性能(感谢 Pierre Arnaud 的性能测试):
要查找在给定
Assembly
中实现接口的所有类型:Modifying Jeff's answer for optimal performance (thanks to performance test by Pierre Arnaud):
To find all types that implement an interface in a given
Assembly
:请注意,如果您有一个通用接口
IMyInterface
那么这将始终返回false
:这也不起作用:
但是,如果
MyType
实现了IMyInterface
这有效并返回true
:但是,您可能在运行时将不知道类型参数
T
。一个有点老套的解决方案是:杰夫的解决方案不那么老套:
这里有一个适用于任何情况的
Type
扩展方法:(请注意上面使用了 linq,它可能比循环慢。)
然后你可以这样做:
Note that if you have a generic interface
IMyInterface<T>
then this will always returnfalse
:This doesn't work either:
However, if
MyType
implementsIMyInterface<MyType>
this works and returnstrue
:However, you likely will not know the type parameter
T
at runtime. A somewhat hacky solution is:Jeff's solution is a bit less hacky:
Here's a extension method on
Type
that works for any case:(Note that the above uses linq, which is probably slower than a loop.)
You can then do:
搜索此内容的任何人可能会发现以下扩展方法很有用:
xunit 测试:
Anyone searching for this might find the following extension method useful:
xunit tests:
IsAssignableFrom
现在移至TypeInfo
:IsAssignableFrom
is now moved toTypeInfo
:正确的答案是
但是,
可能会返回错误的结果,如以下代码所示,使用字符串和 IConvertible:
结果:
A correct answer is
However,
might return a wrong result, as the following code shows with string and IConvertible:
Results:
怎么样
?
what about
?
怎么样
What about
如果你不需要使用反射并且你有一个对象,你可以使用这个:
If you don't need to use reflection and you have an object, you can use this:
您有几种选择:
typeof(IMyInterface).IsAssignableFrom(typeof(MyType))
或(从 .NET 5 开始)等效的逆,typeof(MyType).IsAssignableTo(typeof(IMyInterface) ))
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
nameof
运算符typeof(MyType).GetInterface(nameof(IMyInterface)) ! = null
- 但请注意nameof
不会返回完全限定的类型名称,因此如果您在不同的命名空间中有多个命名相同的接口,您最终可能会得到所有这些接口一个通用接口,它有点复杂:
或者使用 LINQ:
You have a few choices:
typeof(IMyInterface).IsAssignableFrom(typeof(MyType))
or (as of .NET 5) the equivalent inverse,typeof(MyType).IsAssignableTo(typeof(IMyInterface))
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
nameof
operatortypeof(MyType).GetInterface(nameof(IMyInterface)) != null
- but beware thatnameof
does not return the fully-qualified type name, so if you have multiple interfaces named the same in different namespaces, you may end up getting all of themFor a generic interface, it’s a bit more involved:
or with LINQ:
使用
Type.IsAssignableFrom
:Use
Type.IsAssignableFrom
:或者
or
使用
Type.IsAssignableTo
(从 .NET 5.0 开始):
正如几条评论中所述,IsAssignableFrom 可能会因“向后”而被认为令人困惑。
Use
Type.IsAssignableTo
(as of .NET 5.0):As stated in a couple of comments IsAssignableFrom may be considered confusing by being "backwards".