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



在.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中,因此当在调试模式下执行时,上述测试实际上通过了,但在发布模式下失败。基本上不可能在执行过程中重现错误。

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

是否有其他方法可以在运行时确定调用程序集的文件名

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

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

这是基于

  1. MethodImplOptions的文档(它似乎将尾部递归作为一种特殊情况调用)
  2. 此处讨论的CLI规范的引用:

http://bytes.com/topic/c-sharp/answers/509557-race-conditions-c-eventing

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

相关内容

  • 没有找到相关文章

最新更新