C# 控制何时调用静态构造函数

C# 控制何时调用静态构造函数,c#,attributes,static-constructor,C#,Attributes,Static Constructor,在自定义属性的静态构造函数中,我在加载的程序集中搜索用我的属性修饰的所有类,并对它们执行一些操作 我希望在运行时尽快调用静态构造函数,最好在执行static void Main()入口点之前调用。 目前,它只有在我对属性进行一些调用之后才会被调用。我可以在程序的其他地方进行这样的调用,但理想情况下,属性的功能应该是自包含的 为了寻找答案,我读了以下内容: 用户无法控制在程序中何时执行静态构造函数 但肯定有一些棘手的、狡猾的或恶作剧的解决方法来尽快调用静态构造函数。也许可以使用属性、反射或其他魔法

在自定义属性的静态构造函数中,我在加载的程序集中搜索用我的属性修饰的所有类,并对它们执行一些操作

我希望在运行时尽快调用静态构造函数,最好在执行
static void Main()
入口点之前调用。

目前,它只有在我对属性进行一些调用之后才会被调用。我可以在程序的其他地方进行这样的调用,但理想情况下,属性的功能应该是自包含的

为了寻找答案,我读了以下内容:

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

但肯定有一些棘手的、狡猾的或恶作剧的解决方法来尽快调用静态构造函数。也许可以使用属性、反射或其他魔法可以吗?

因为人们无疑会告诉我,没有很好的理由去做我要求的事情,所以我给出了我的目的和代码:我试图使用属性来声明性地配置工厂。如果我的属性的静态构造函数是在我已经建立了连接之后调用的,那么它就没有效果,也没有用处。因此,必须在我的程序有机会建立这种连接之前调用它


如果希望调用静态构造函数,则向类型添加一个伪方法,并在代码的开头调用它(
Main
etc);如果它是一个普通/空的方法,您可能希望将其标记为无内联等

class SomeType {
    static SomeType() {
        Console.WriteLine("SomeType.cctor");
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void Init() { }
}

static class Program {
    static void Main() {
        SomeType.Init();
        Console.WriteLine("hi");
    }
}

您可以使用反射来调用静态构造函数,但我不建议这样做;如果您使用反射,实际上可以多次调用.cctor,这从来都不是一件好事…

正如Marc所说,如果我是您,我会在
Main
中明确地执行此操作

您可以使用属性显式地调用类型的类型初始值设定项并调用它。但是,这将导致它再次运行,即使它已经运行过,这可能会产生意外的结果

我个人会将代码完全移出静态初始值设定项。这是配置代码——为什么不把它变成一个可以显式调用的静态方法呢?我甚至不确定属性类本身是否包含它,但至少显式调用:

CascadeOnUpdateAttribute.ConfigureDb4oFactories();

比调用伪方法或以其他方式强制类型初始化更清晰,只是为了得到一个副作用。

我认为使用静态构造函数有异味;我会考虑重构您的代码来控制对D4O工厂的访问,这样您就不需要使用它。

< P>您可以通过调用< /P>避免静态哑方法。
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(CascadeOnUpdateAttribute).TypeHandle)

我不会对气味进行争论,但知道如何更快地调用构造函数还是很有趣的。如果Init被内联,为什么会如此糟糕?如果它没有内联,我会想:它被调用了吗;如果没有调用,是否调用了.cctor?
class SomeType {
    static SomeType() {
        Console.WriteLine("SomeType.cctor");
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void Init() { }
}

static class Program {
    static void Main() {
        SomeType.Init();
        Console.WriteLine("hi");
    }
}
CascadeOnUpdateAttribute.ConfigureDb4oFactories();
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(CascadeOnUpdateAttribute).TypeHandle)