2008-09-23 124 views
6

好吧,所以我碰到以下问题,提出了眉毛。Assembly.GetCallingAssembly()和静态构造函数?

由于各种原因,我有一个测试设置,其中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,它应该是调用者。有谁知道可能发生了什么?

回答

5

静态构造函数是在执行上没有控制由运行时调用,而不是由用户代码直接调用。您可以通过在构造函数中设置断点并在调试器中运行来看到这一点。紧挨着它的调用链中的函数是本地代码。

编辑:静态初始化器在其他用户代码中运行的环境有很多种。其他一些方法是

  1. 他们免受多线程
  2. 不能从初始化

一般外面捕捉异常导致竞争条件暗中保护,它可能是最好不要使用它们因为任何事情都太复杂您可以使用以下模式实现单启动:

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

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

+0

那么为什么调用程序集不是null呢? – 2008-09-23 16:23:11

1

我认为答案在这里讨论C# static constructors。我最好的猜测是,静态构造函数正从一个意想不到的情况下调用,因为:

用户具有当 静态构造函数在 程序

+0

其实你有一些控制:) – leppie 2008-12-04 16:12:54

1

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