如何在.NET 4.0中可靠地确定调用程序集

时间:2011-06-22 15:58:35

标签: .net reflection clr

在.NET 3.5及更低版本中,以下(略显粗略的示例)运行良好:

大会A:

public static class ClassInAssemblyA
{
    public static string GetCallingAssemblyLocation()
    {
        return System.Reflection.Assembly.GetCallingAssembly().GetName(false).CodeBase;
    }
}

大会B:

public class ClassInAssemblyB
{
    public string AssemblyName { get; private set; }

    public ClassInAssemblyB()
    {
        AssemblyName = ClassInAssemblyA.GetCallingAssemblyLocation();
    }
}

装配C:

var assemblyName = new ClassInAssemblyB().AssemblyName;
Assert.That(assemblyName.Contains("AssemblyB"));

不幸的是,.NET 4.0 CLR似乎已经过优化,可以将AssemblyA代码内联到AssemblyB中,因此上述测试在Debug模式下执行时实际通过,但在发布模式下失败。在单步执行时,基本上不可能重现错误。

停止内联的一种方法是每次引用AssemblyA时都要求调用者添加属性[MethodImpl(MethodImplOptions.NoInlining)]。这是一个kludgy解决方案,需要调用者知道库的内部工作,它不应该是他们的问题,所以我不愿意走这条路。

有没有其他方法可以在运行时弄清楚调用程序集的文件名是什么

2 个答案:

答案 0 :(得分:1)

除了使用MethodImplOptions.NoInlining之外,我认为没有其他解决方案。请参阅GetCallingAssembly的文档,其中包括几乎所有情况。另外,请注意,您需要将属性添加到两者 A中的方法和B中的方法,因为内联到其调用程序集中会导致您看到的行为。

答案 1 :(得分:0)

我的理解是,在您尝试测试自递归调用的情况下,JIT编译器将始终尊重[Flags(MethodImplOptions.NoInlining)],但可能

这是基于

  1. MethodImplOptions的文档(似乎将尾递归称为特殊情况)
  2. 此处讨论的CLI规范的引用:
  3. http://bytes.com/topic/c-sharp/answers/509557-race-conditions-c-eventing

    (据我所知,它没有讨论尾递归)

相关问题