为什么Type.GetInterfaces()有时不返回有效列表?

时间:2012-09-20 20:35:35

标签: c# wcf reflection

我们继承了一个设计不合理的WCF服务,我们希望改进它。它的一个问题是它有超过一百种方法(在两个不同的接口上),其中大多数我们怀疑没有使用。我们决定对每种方法进行一些记录,以跟踪它们何时以及如何被调用。为了使跟踪代码具有重构友好性和防错性,我们实现了它:

public void LogUsage()
{
    try
    {
        MethodBase callingMethod = new StackTrace().GetFrame(1).GetMethod();
        string interfaceName = callingMethod.DeclaringType.GetInterfaces()[0].Name;
        _loggingDao.LogUsage(interfaceName, callingMethod.Name, GetClientAddress(), GetCallingUrl());
    }
    catch (Exception exception)
    {
        _legacyLogger.Error("Error in usage tracking", exception);
    }
}
然后在我们想要跟踪的每个方法的开头调用

LogUsage()

该服务的流量非常高,每天有500,000多个电话。 99.95%的时间,这段代码执行得很漂亮。但是另外0.05%的时间,GetInterfaces()返回一个空的(但不是null)数组。

为什么GetInterfaces()偶尔会返回不一致的结果?

这看起来似乎微不足道 - 0.05%的错误率是我们通常只能梦想的。但重点是识别所有服务接触点,如果此错误总是来自一个(或几个)方法调用,那么我们的跟踪是不完整的。我试图通过调用服务上的每个方法在我的开发环境中重现此错误,但无济于事。

2 个答案:

答案 0 :(得分:4)

众所周知,

StackTrace不可靠,尤其是在多线程环境中。或者说,它非常可靠,但有时不太实用。询问“最后一个被调用的方法”会产生意想不到的结果。尝试记录DeclaringType。您可能会对在那里找到的东西感到惊讶。请注意,虽然现在这是一个0.05%的失败率,但随着应用程序的复杂性,它很容易增加。

为了正确实现可重用的跟踪代码,您需要依赖.NET 4.5功能Caller Information,使用动态代理(例如Castle Dynamic Proxy)或使用AOP框架例如PostSharp。或者,您可以手动编写跟踪代码。

答案 1 :(得分:3)

来自Erik Lippert(负责MS的C#编译团队)回应Getting Type T from a StackFrame

  

堆栈框架实际上并没有告诉你谁调用了你的方法。该   堆栈框架告诉您控件将返回的位置。堆栈   框架是延续的具体化。谁叫谁的事实   方法和控制将返回的位置几乎总是相同的   事情是你困惑的根源,但我向你保证他们需要   不一样。

整个帖子值得一读......