使用反射检查方法是否实现了IDisposable.Dispose。

7

是否有更正式/更可靠的方法来检查 System.Reflection.MethodInfo 是否引用类对 IDisposable.Dispose 的实现,而不是以下方式?

System.Reflection.MethodInfo methodInfo;
methodInfo = ...; //methodInfo obtaining code here
bool isDisposeMethod = methodInfo.Name == "Dispose";

我已经知道这个类实现了IDisposable接口,因此有Dispose方法,但是我正在使用PostSharp方面,当调用Dispose时应该执行特殊功能(与任何其他类方法相比)。


1
如果一个类实现了 IDisposable 接口,那么你可以保证它实现了 Dispose 方法 - 这就是该接口的目的。 - Blorgbeard
我理解了。我知道Dispose的存在,但我使用的是PostSharp方面,在调用Dispose时应该执行特殊功能,与另一个函数相比不同。PostSharp方面在System.Reflection.MethodInfo中返回方法签名。 - Fabian Tamp
3个回答

6

拥有:

class DisposableObject : IDisposable
{
    public void Dispose()
    {
        //...
    }
}

你可以做:
Type t = typeof(DisposableObject);

InterfaceMapping m = t.GetInterfaceMap(typeof(IDisposable));
MethodInfo mi = t.GetMethod("Dispose");

Console.WriteLine(mi == m.TargetMethods[0]); //true

因此,我假设您有类中某个Dispose方法的MethodInfo(在这里通过GetMethod(string)获得的mi)。然后,您需要通过Type.GetInterfaceMap Method获取声明类型(这里为DisposableObject)中IDisposable实现的InterfaceMapping Structure对象。在那里,您可以找到TargetMethods引用实际实现接口的方法。所以,我们只需要检查您的引用是否等于m.TargetMethods[0],因为IDisposable仅声明了一个方法。

来自MSDN:

InterfaceMapping 结构

检索将接口映射到实现该接口的类上的实际方法。

当类型实现使用与接口指定的方法名称不同的方法名称的接口方法,或者当类型实现具有相同名称的方法的多个接口时,使用 InterfaceMapping 结构。

要获取 InterfaceMapping 结构,请使用 Type.GetInterfaceMap 方法。


有一个注意事项:如果您的类可以显式实现 IDisposable,那么m.TargetMethods [0]将引用显式实现。所以,我不确定是否有任何方法可以获取它的 MethodInfo,除了使用 InterfaceMapping(请参见使用反射查找实现显式接口的方法)。这种情况可能容易出错。针对您的具体问题进行检查。


谢谢您的回答。我不是试图检查对象是否实现了“IDisposable” - 这只是“bool test = myObj is IDispoable”的问题 - 我正在尝试测试特定的“MethodInfo”是否指的是类对“IDisposable.Dispose”的实现。 - Fabian Tamp
谢谢。我已经检查过了 - 应该没问题 :) - Fabian Tamp

4
我认为正确的方法是在类型上获取“IDisposable”的接口,然后根据接口对象获取方法信息。然后,您应该能够将手头的方法与从接口返回的方法进行比较。
仅检查名称是不够的,因为:
- 可能会有其他具有相同名称但参数不同的方法 - 接口可能被显式实现
这里是一个展示两个问题的类:
class Test : IDisposable
{
   public void Dispose(){}
   public void Dispose(bool flag){}
   void IDisposable.Dispose(){} 
}

3

我认为这可能适用于您的情况,虽然代码不够美观,但它会返回方法信息是否来自一个IDisposable类。

System.Reflection.MethodInfo methodInfo;
methodInfo = ...; //methodInfo obtaining code here
bool isDisposible = methodInfo.DeclaringType.FindInterfaces(new System.Reflection.TypeFilter((type, filter) => { return type.ToString() == filter.ToString(); }), "System.IDisposable").Any();

不确定这是否符合您的需求。

这也是一个很好的答案。我将你和Konstantin Vasilcov提供的内容合并成了以下代码: bool isDisposible = methodInfo.DeclaringType.GetInterfaceMap(typeof(IDisposable)).TargetMethods.Where(x => x == methodInfo).Any(); - Fabian Tamp
2
你可以在上面的方法中省略"Where"子句,只需使用以下代码:bool isDisposible = methodInfo.DeclaringType.GetInterfaceMap(typeof(IDisposable)).TargetMethods.Any(x => x == methodInfo); - sa_ddam213

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接