简体   繁体   English

强制构造静态物体

[英]Force construction of static objects

As I've learned the static objects in classes are constructed when the class is being referenced for the first time. 正如我所知,类中的静态对象是在第一次引用类时构造的。 However I'd find it sometimes usefull to initialize the statics when the program is being started. 但是我发现在程序启动时初始化静态有时很有用。 Is there some method (ie by using annotations) of enforcing it? 是否有一些方法(即通过使用注释)来执行它?

You can't do it with attributes (without extra code), but you can force type initialization with reflection. 你不能用属性(没有额外的代码)来做,但你可以用反射强制类型初始化。

For example: 例如:

foreach (Type type in assembly.GetTypes())
{
    ConstructorInfo ci = type.TypeInitializer;
    if (ci != null)
    {
         ci.Invoke(null);
    }
}

Note that this won't invoke type initializers for generic types, because you'd need to specify the type arguments. 请注意,这不会为泛型类型调用类型初始值设定项,因为您需要指定类型参数。 You should also note that it will force the type initializer to be run even if it's been run already which flies in the face of normal experience. 您还应该注意,它将强制运行类型初始化程序, 即使它已经运行过,面对正常体验也是如此。 I would suggest that if you really need to do this (and I'd try to change your design so you don't need it if possible) you should create your own attribute, and change the code to something like: 我建议如果你真的需要这样做(我会尝试改变你的设计,如果可能你不需要它)你应该创建自己的属性,并将代码改为:

foreach (Type type in assembly.GetTypes())
{
    if (type.GetCustomAttributes(typeof(..., false)).Length == 0)
    {
        continue;
    }
    ConstructorInfo ci = type.TypeInitializer;
    if (ci != null)
    {
         ci.Invoke(null, null);
    }
}

You could do this with LINQ, admittedly: 你可以用LINQ做到这一点,诚然:

var initializers = from type in assembly.GetTypes()
                   let initializer = type.TypeInitializer
                   where initializer != null &&
                         type.GetCustomAttributes(typeof(..., false).Length > 0
                   select initializer;
foreach (ConstructorInfo initializer in initializers)
{
    initializer.Invoke(null, null);
}

Simply reference a static field on that type at the beginning of your application. 只需在应用程序开头引用该类型的静态字段。 There's no way of doing this solely by altering the code at the class definition site . 没有办法单独通过改变类定义站点的代码来实现这一点。

您可以使用RuntimeHelpers.RunClassConstructor运行任意类型的初始值设定项

The CLR supports module initializers , that's probably what you are looking for. CLR支持模块初始化器 ,这可能就是您正在寻找的。 Rather academic given your tags though, this feature is not available in the C# language, only the C++/CLI language. 相反,考虑到你的标签,这个功能在C#语言中是不可用的,只有C ++ / CLI语言。

The workaround is entirely painless, call a static method (Initialize?) explicitly. 解决方法完全无痛,请显式调用静态方法(Initialize?)。

Ok, I found out that this can be done in the following way. 好的,我发现这可以通过以下方式完成。 A single call to InvokeImplicitInitializers() in Main() will be call Initialize() in every class that has defined that method. 在Main()中调用InvokeImplicitInitializers()将在已定义该方法的每个类中调用Initialize()。

using System;
using System.Reflection;

namespace Test
{
    public class Class1
    {
        static Class1()
        {
            Console.WriteLine("Class1: static constructor");
        }

        public static void Initialize()
        {
            Console.WriteLine("Class1: initialize method");
        }
    }

    public static class Class2
    {
        public static void Initialize()
        {
            Console.WriteLine("Class2: initialize method");
        }
    }


    class MainClass
    {
        public static void InvokeImplicitInitializers(Assembly assembly)
        {
            foreach (Type type in assembly.GetTypes())
            {
                MethodInfo mi = type.GetMethod("Initialize");
                if (mi != null) 
                {
                    mi.Invoke(null, null);
                }
            }
        }

        public static void Main (string[] args)
        {
            InvokeImplicitInitializers(Assembly.GetCallingAssembly());
        }
    }
}

What do you think? 你怎么看? Is it a pattern or anit-pattern? 它是模式还是模式?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM