Подтвердить что ты не робот

Как инициализировать статический класс С# до того, как он действительно понадобится?

У меня есть статический класс со статическим конструктором, который занимает некоторое время (10-15 секунд), чтобы выполнить и полностью инициализировать класс. Чтобы повысить производительность, я решил включить этот статический класс в явную инициализацию вместо того, когда он сначала понадобится, чтобы он был готов к работе, когда он действительно должен использоваться.

Моя первая мысль заключалась в создании метода Initialize() для класса, но поскольку у меня уже есть статический конструктор, этот метод, похоже, не должен делать ничего, кроме метода, чтобы вызвать явное инициализацию класса без доступа к каким-либо другим общедоступным методам или свойствам. Мне кажется, что метод, который ничего не делает, прямо мне не подходит.

Затем я подумал, что могу просто переместить код из статического конструктора в этот метод Initialize(), но мне также хотелось бы, чтобы класс был инициализирован, когда он сначала нужен, и метод Initialize() не был явно вызван.

Подводя итог, хочу отметить следующие критерии:

  • Я хочу, чтобы статический класс был явно инициализирован (вероятно, используя общедоступный метод Initialize()).
  • Я не хочу иметь доступ к каким-либо другим общедоступным методам или свойствам класса, когда они мне не нужны, даже если это будет инициализировать статический класс.
  • Если класс не был явно инициализирован, я все же хочу инициализировать его, когда он сначала необходим (т.е. при доступе к другим общедоступным методам или свойствам с целью использования функциональных возможностей или данных, которые они предоставляют).
  • Это вспомогательный класс, и использование шаблона проектирования Singleton для моих целей необязательно.

Каким будет правильный способ соблюдения вышеуказанных критериев для статического класса, написанного на С#? Это может также относиться к другим языкам программирования (например, Java), но лично меня интересует решение, написанное на С#.

4b9b3361

Ответ 1

Я бы, наверное, просто пошел за методом Initialize - и он может сделать что-то полезное:

  • Он может регистрировать, что вы явно пытаетесь инициализировать класс, с трассировкой стека
  • Это может вызвать исключение, если класс уже инициализирован с помощью другого вызова Initialize
  • Вы могли бы (с небольшими усилиями и реорганизацией) сортировать вещи, чтобы любые исключения, вызванные при инициализации, распространялись без TypeInitializationException, который вы обычно получали.

Ответ 2

Я бы пошел с методом initialize (EDIT: см. ответ Jon). Но если вы действительно хотите использовать конструктор, вы можете сделать это:

var type = typeof (YourType);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);

RunClassConstructor позволяет принудительно запускать конструктор классов (статический конструктор), если он уже не имеет. Если он уже запущен, скажем, потому что вы использовали статический член класса, это не имеет никакого эффекта. Выполнение этого дополнительного времени не влияет.

Ответ 3

Я не уверен, что вы можете указать, когда загружается статический конструктор.

Из MSDN "Статический конструктор вызывается автоматически для инициализации класса до создания первого экземпляра или ссылки на любые статические члены".

http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx

* EDIT: * Добавил бы здесь синтаксический шаблон? Геттер может вызвать Initialize(), проверив флаг в классе, IsLoaded = true. Последующие вызовы не будут вызывать Initialize()

Ответ 4

Два обхода:

  • Переместите код конструктора на Initialize(), чтобы вы могли явно позвонить. И замените код внутри конструктора, чтобы просто вызвать метод Initialize(), если статический класс загружается динамически, прежде чем вы вызываете его явно

    public static class StaticClass
    {
        // actual constructor
        static StaticClass()
        {
            Initialize();
        }
    
        // explicit "constructor"
        public static void Initialize()
        {
            MyProperty = "Some Value";
        }
    
        public static string MyProperty { get; set; }
    
    }
    

    Затем выполните инициализацию, если хотите:

    StaticClass.Initialize();
    

    Или он будет динамически инициализирован при первом использовании

  • Не как семантически первозданный, но вы можете инициировать органическую инициализацию статического класса, просто потребляя свойство и бросая его во временную переменную.

    Так просто сделайте это:

    // trigger static initilaization
    var dummy = StaticClass.MyProperty;
    

    Все еще позволяет вам называть его всякий раз, когда вам нужно, но если при инициализации есть некоторая производительность, вы можете попытаться вызвать его при запуске, а не в первый раз, когда пользователь делает что-то, что срабатывает для этого кода.

Для другой полезной схемы статической инициализации см.: Является ли порядок инициализации статического класса в С# детерминированным?

Ответ 5

Подход не кажется мне нехорошим. Я могу назвать метод Touch(), дать ему пустое тело и добавить соответствующий комментарий. Будет ли это достаточно, чтобы рассказать вам о том, что что-то не так хорошо?