【问题标题】:Explicitly call static constructor显式调用静态构造函数
【发布时间】:2012-07-16 06:37:16
【问题描述】:

我想为下面的课程编写单元测试。
如果名称不是“MyEntity”,则 mgr 应为空白。
负单元测试
使用 Manager 私有访问器,我想将名称更改为“Test”,以便 mgr 应该为空。 然后将验证经理值。 为此,我想显式调用静态构造函数 但是当我使用

调用静态构造函数时
Manager_Accessor.name = "Test"
typeof(Manager).TypeInitializer.Invoke(null, null); 

name 始终设置为“MyEntity”如何将 name 设置为“Test”并调用静态构造函数。

public class Manager
{        
        private static string name= "MyEntity";

        private static object mgr;

        static Manager()
        {
            try
            {
                mgr = CreateMgr(name);
            }
            catch (Exception ex)
            {
                mgr=null;
            }
        }
}

【问题讨论】:

  • 使 'mgr' 静态意味着 所有 'Manager' 实例共享 same 'mgr' 值,该值也永远无法更改(如它是只读的)。这真的是你想要的吗?
  • 所以您需要更改一个私有硬编码静态值,该值负责设置私有静态只读值以用于测试目的?这就是为什么大多数可测试性设计选择不喜欢静态。

标签: c# mstest system.reflection static-constructor


【解决方案1】:

今天发现,可以直接调用静态构造函数:

来自another Stackoverflow post

其他答案都很好,但如果你需要强制上课 构造函数在没有引用类型的情况下运行(即。 反射),您可以使用:

Type type = ...;
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);  

我必须将此代码添加到我的应用程序to work around a possible bug in the .net 4.0 CLR

【讨论】:

    【解决方案2】:

    对于任何发现此线程并想知道...我刚刚进行了测试。看来System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor() 只会在静态构造函数出于其他原因运行时才运行。

    例如,如果您的代码不确定之前的代码是否已经访问了该类并触发了静态构造函数运行,这无关紧要。先前的访问将触发静态构造函数运行,但 RunClassConstructor() 也不会运行它。 RunClassConstructor() 仅在静态构造函数尚未运行时才运行它。

    在 RunClassConstructor() 之后访问类也不会导致静态构造函数再次运行。

    这是基于在 Win10 UWP 应用中的测试。

    【讨论】:

    • 这让我非常难过,因为现在每当我想重置我的静态类的值时,我都需要调用它的静态方法,该方法与构造函数所做的完全相同——设置默认值。
    • 正确。您不会再次“构建”对象。只设置它们的值。假设您已经构建了一个非静态对象并将对它的引用存储在代码中的许多不同位置。现在您要重置对象的值。您不会再次重建(“新”)对象。所有那些旧的存储引用仍然是旧对象。相反,您将有一个方法可以重置已构建对象的值。然后你会意识到构造函数和 reset 方法在做同样的事情,所以你只是从构造函数中调用了 reset 方法。
    • 在此处查看答案:stackoverflow.com/a/51758748/1662268 如果您需要它重复运行该怎么办。
    【解决方案3】:

    如果你的类中有一个静态成员(必须有,否则静态构造函数不会做太多),那么不需要显式调用静态构造函数。

    只需访问您想要调用其静态构造函数的类。 例如:

    public void MainMethod()
    {
        // Here you would like to call the static constructor
    
        // The first access to the class forces the static constructor to be called.
        object temp1 = MyStaticClass.AnyField;
    
        // or
        object temp2 = MyClass.AnyStaticField;
    }
    

    【讨论】:

      【解决方案4】:

      只需将 public static void Initialize() { } 方法添加到您的静态类中,并在需要时调用它。这和调用构造函数非常相似,因为静态构造函数会被自动调用。

      【讨论】:

      • 我认为这是正确的答案。它不依赖于未指定的(我无论如何都能找到)RunClassConstructor 行为,它只会执行一次静态构造函数。在类上调用空的“Initialize()”具有在 C# 语言定义中指定的行为,可以依赖。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多