Assembly.GetCallingAssembly () and static constructors?

Okay, so I just ran into the next problem that raised an eyebrow.

For various reasons, I have a test setup where the test classes in TestingAssembly.dll depend on the TestingBase class in BaseTestingAssembly.dll. One of the tasks that TestBase performs is finding a specific built-in resource in its own and calling assembly.

So my BaseTestingAssembly contained the following lines ...

public class TestBase { private static Assembly _assembly; private static Assembly _calling_assembly; static TestBase() { _assembly = Assembly.GetExecutingAssembly(); _calling_assembly = Assembly.GetCallingAssembly(); } } 

Static, because I realized that these assemblies will be the same throughout the life of the application, so why bother with recounting them in each individual test.

While doing this, however, I noticed that both _assembly and _calling_assembly are set to BaseTestingAssembly, not BaseTestingAssembly and TestingAssembly respectively.

Setting the variables to non-static and initializing them in the regular constructor fixed this, but I'm confused why this happened to start this. I thought that static constructors are launched the first time a static member gets a reference. This can only be from my TestingAssembly, which was supposed to be caller. Does anyone know what could happen?

+6
reflection c # static-constructor
source share
3 answers

The static constructor is called by the runtime, and not directly by the user code. You can see this by setting a breakpoint in the constructor and then running it in the debugger. The function immediately above it in the call chain is its own code.

Edit: There are many ways to run static initializers in a different environment than different user code. Some other ways:

  • They are implicitly protected from race conditions as a result of multithreading
  • You cannot catch exceptions from outside the initializer

In general, it’s best not to use them for something too complicated. You can implement single-init with the following pattern:

 private static Assembly _assembly; private static Assembly Assembly { get { if (_assembly == null) _assembly = Assembly.GetExecutingAssembly(); return _assembly; } } private static Assembly _calling_assembly; private static Assembly CallingAssembly { get { if (_calling_assembly == null) _calling_assembly = Assembly.GetCallingAssembly(); return _calling_assembly; } } 

Add a lock if you expect multithreaded access.

+5
source share

I think the answer here is in a discussion of C # static constructors . My best guess is that the static constructor gets called from an unexpected context, because:

The user cannot control when the static constructor is executed in the program

+1
source share

Assembly.GetCallingAssembly () simply returns the assembly of the second record in the call stack. This can greatly depend on how the / getter / constructor method is called. Here is what I did in the library to get the assembly of the first method, which is not in my library. (This even works in static constructors.)

 private static Assembly GetMyCallingAssembly() { Assembly me = Assembly.GetExecutingAssembly(); StackTrace st = new StackTrace(false); foreach (StackFrame frame in st.GetFrames()) { MethodBase m = frame.GetMethod(); if (m != null && m.DeclaringType != null && m.DeclaringType.Assembly != me) return m.DeclaringType.Assembly; } return null; } 
+1
source share

All Articles