How to reliably determine the calling assembly in .NET 4.0
In .NET 3.5 and lower, the following (slightly crude example) works pretty well:
Assembly A:
public static class ClassInAssemblyA
{
public static string GetCallingAssemblyLocation()
{
return System.Reflection.Assembly.GetCallingAssembly().GetName(false).CodeBase;
}
}
Assembly B:
public class ClassInAssemblyB
{
public string AssemblyName { get; private set; }
public ClassInAssemblyB()
{
AssemblyName = ClassInAssemblyA.GetCallingAssemblyLocation();
}
}
Assembly C:
var assemblyName = new ClassInAssemblyB().AssemblyName;
Assert.That(assemblyName.Contains("AssemblyB"));
Unfortunately the .NET 4.0 CLR seems to be optimized to i开发者_运维知识库nline the AssemblyA code into AssemblyB, and so the above test actually passes when executed in Debug mode, but fails in release mode. It's basically impossible to reproduce the error while stepping through.
One way to stop the inlining is to require the caller to add the attribute [MethodImpl(MethodImplOptions.NoInlining)]
every time they reference AssemblyA. This is a kludgy solution that requires the caller to know the inner workings of the library, and it shouldn't be their problem, so I am not willing to go this route.
Are there any alternative ways to figure out at runtime what the filename is of the calling assembly?
I don't think there's any solution other than using MethodImplOptions.NoInlining
. See the documentation for GetCallingAssembly, which includes almost this exact scenario. Also, note that you need to add the attribute to both the method in A and the method in B, since inlining either into its calling assembly would result in the behavior that you're seeing.
My understanding is that JIT compiler will always respect [Flags(MethodImplOptions.NoInlining)]
except possibly in the case that you are trying to test a self-recursive call.
This is based on
- the documentation of MethodImplOptions (which seems to call out tail recursion as a special case)
- a quotation of the CLI spec discussed here:
http://bytes.com/topic/c-sharp/answers/509557-race-conditions-c-eventing
(which didn't discuss tail recursion as far as I read)
精彩评论