好的,所以我遇到了以下引起挑眉的问题。

由于各种原因,我有一个测试设置,其中TestingAssembly.dll中的测试类依赖于BaseTestingAssembly.dll中的TestingBase类。 TestBase在此期间所做的一件事就是在自己和调用程序集中查找某个嵌入式资源

所以我的BaseTestingAssembly包含以下几行......

public class TestBase {    
  private static Assembly _assembly;
  private static Assembly _calling_assembly;

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

静态,因为我认为,这些程序集在应用程序的生命周期内是相同的,所以为什么还要在每次测试时重新计算它们。

当运行它时,我注意到_assembly和_calling_assembly分别设置为BaseTestingAssembly而不是BaseTestingAssembly和TestingAssembly。

将变量设置为非静态并将它们初始化为常规构造函数修复此问题,但我很困惑为什么会发生这种情况。我认为静态构造函数在第一次引用静态成员时运行。这可能只来自我的TestingAssembly,那时应该是调用者。有谁知道可能发生了什么?

有帮助吗?

解决方案

静态构造函数由运行时调用,而不是由用户代码直接调用。您可以通过在构造函数中设置断点然后在调试器中运行来查看。调用链中紧邻其上方的函数是本机代码。

编辑:静态初始化程序在很多方面的运行方式与其他用户代码不同。其他一些方法是

  1. 他们受到多线程导致的竞争条件的隐含保护
  2. 您无法从初始化程序之外捕获异常
  3. 一般来说,最好不要将它们用于任何过于复杂的事情。您可以使用以下模式实现single-init:

    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;
      }
    }
    

    如果您希望进行多线程访问,请添加锁定。

其他提示

我认为答案就在的讨论中。 C#静态构造函数。我最好的猜测是静态构造函数是从意外的上下文调用的,因为:

  

用户无法控制何时   静态构造函数在。中执行   程序

Assembly.GetCallingAssembly()只返回调用堆栈中第二个条目的程序集。这可能取决于你的方法/ getter /构造函数的调用方式。这是我在库中做的,以获取不在我的库中的第一个方法的程序集。 (这甚至适用于静态构造函数。)

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;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top