在.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解决方案,需要调用者知道库的内部工作,它不应该是他们的问题,所以我不愿意走这条路。
有没有其他方法可以在运行时弄清楚调用程序集的文件名是什么?
答案 0 :(得分:1)
除了使用MethodImplOptions.NoInlining
之外,我认为没有其他解决方案。请参阅GetCallingAssembly的文档,其中包括几乎所有情况。另外,请注意,您需要将属性添加到两者 A中的方法和B中的方法,因为内联到其调用程序集中会导致您看到的行为。
答案 1 :(得分:0)
我的理解是,在您尝试测试自递归调用的情况下,JIT编译器将始终尊重[Flags(MethodImplOptions.NoInlining)]
,但可能。
这是基于
http://bytes.com/topic/c-sharp/answers/509557-race-conditions-c-eventing
(据我所知,它没有讨论尾递归)