Явное вызов статического конструктора

23

Я хочу написать модульный тест для ниже класса.
Если имя отличается от «MyEntity», то mgr должен быть пустым.
Отрицательный модульный тест
Использование диспетчера private accessor Я хочу изменить имя на «Test», чтобы mgr должен был быть нулевым. А затем проверит значение mgr. Для этого я хочу явно вызвать статический конструктор но когда я вызываю статический конструктор, используя

Manager_Accessor.name = "Test"
typeof(Manager).TypeInitializer.Invoke(null, null); 

name всегда устанавливается в «MyEntity», как установить имя для «Test» и вызвать статический конструктор.

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

        private static object mgr;

        static Manager()
        {
            try
            {
                mgr = CreateMgr(name);
            }
            catch (Exception ex)
            {
                mgr=null;
            }
        }
}
    
задан meetjaydeep 17.07.2012 в 12:42
источник
  • Создание статики «mgr» означает, что все экземпляры «Диспетчера» имеют одно и то же значение «mgr», которое также никогда не может быть изменено (поскольку оно только для чтения). Это действительно то, что вы хотите? –  Hans Kesting 17.07.2012 в 12:46
  • Итак, вам нужно изменить частное статическое значение жесткого кодирования, которое отвечает за установку частного статического значения readonly для целей тестирования? Вот почему большинство вариантов дизайна для тестирования не нравятся статике. –  Adam Houldsworth 17.07.2012 в 12:56

4 ответа

30

Как я узнал сегодня, статический конструктор CAN можно вызвать напрямую:

из другого сообщения Stackoverflow

  

Другие ответы превосходны, но если вам нужно заставить класс   конструктор для запуска без ссылки на тип (т.е.   отражение), вы можете использовать:

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

Мне пришлось добавить этот код в мое приложение , чтобы обойти возможную ошибку в .NET 4.0 CLR .     

ответ дан Tobias Knauss 08.04.2015 в 11:51
источник
4

Если у вас есть статический член в вашем классе (должен быть, иначе статический конструктор не будет делать слишком много), тогда нет необходимости явно вызывать статический конструктор.

Просто доступ к классу, где вы хотите вызвать его статический конструктор. Например:.

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;
}
    
ответ дан Mitulát báti 14.09.2016 в 21:55
источник
2

Для тех, кто найдет эту тему и задается вопросом ... Я просто сделал тест. Похоже, что System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor() запускает только статический конструктор, если он уже имеет не по другой причине.

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

Доступ к классу после того, как RunClassConstructor () также выполняет не , приводит к тому, что статический конструктор запускается второй раз.

Это основано на тестировании в приложении UWP Win10.

    
ответ дан kburgoyne 15.06.2017 в 02:18
источник
  • Это делает меня невероятно грустным, как сейчас, когда я хочу сбросить значения моего статического класса. Мне нужно вызвать его статический метод, который делает то же самое, что и конструктор, - устанавливает значения по умолчанию. –  A Lazy Doe 28.02.2018 в 13:46
  • Исправить. Вы еще не «конструируете» объекты. Только установление их значений. Предположим, что вы уже создали нестатический объект и сохранили ссылки на него в связке разных мест вашего кода. Теперь вы хотите сбросить значения объекта. Вы не будете повторно восстанавливать («новый») объект. Все эти старые сохраненные ссылки по-прежнему относятся к старому объекту. Вместо этого у вас будет метод, который сбросит значения на уже построенный объект. Тогда вы поймете, что конструктор и методы сброса делали то же самое, поэтому вы просто вызвали метод сброса из конструктора. –  kburgoyne 01.03.2018 в 16:37
0

Поместите код, который вы хотите вызвать в конструкторе, в открытый метод и вызовите его из конструктора

    
ответ дан hngr18 11.08.2017 в 19:22
источник