TransWikia.com

Как имитировать событие для отладки?

Stack Overflow на русском Asked by cProject on February 13, 2021

Код

System.Timers.Timer  t2 = new System.Timers.Timer() ;
t2.Elapsed += OnTimedEvent0;
//OnTimedEvent0 должен быть :
public void OnTimedEvent0(Object source, System.Timers.ElapsedEventArgs e);

Как вызвать OnTimedEvent0?

Инициализация Arg1,Arg2;
OnTimedEvent0(Arg1, Arg2);

One Answer

Вопрос не так прост, как кажется.

Конечно, если нужно просто вызвать событие, то достаточно написать (как уже указано в комментарии):

OnTimedEvent0(null, null);

Но что, если в обработчике события эти параметры как-то используются?

Первым параметром нужно передать экземпляр таймера, который возбуждает это событие:

OnTimedEvent0(t2, null);

А вот со вторым есть проблема: класс ElapsedEventArgs имеет закрытый конструктор и его экземпляр невозможно создать напрямую.

Используем рефлексию. Пример кода взят отсюда: https://stackoverflow.com/a/43619543/5045688

using System.Reflection;
using System.Runtime.Serialization;
var signalTime = DateTime.Now;

var e = FormatterServices.GetUninitializedObject(typeof(ElapsedEventArgs)) as ElapsedEventArgs;
if (e != null)
{
    var fieldInfo = e.GetType().GetField("signalTime", BindingFlags.NonPublic | BindingFlags.Instance);
    if (fieldInfo != null)
    {
        fieldInfo.SetValue(e, signalTime);
    }
}

Теперь можно вызвать

OnTimedEvent0(t2, e);

Простите, погорячился. Сдуру ударился в рефлексию, позабыв про правильную архитектуру и всё такое.

Правильным решением будет следующее. Вся логика должна быть размещена в классе предметной модели. Или по крайней мере в отдельном методе. А в обработчике тика таймера просто вызываем этот метод.

// Обработчик события тика таймера
void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
    // просто вызываем другой метод
    ProcessTimerTick(...);
    // метод может быть размещён в другом классе,
    // тогда вызываем его у экземпляра того класса
    _timerProcessor.ProcessTimerTick(...);
}

void ProcessTimerTick(...)
{
    // здесь код обработки события таймера
}

Осталось определиться с сигнатурой метода.

Если нам не нужны данные от таймера, тогда делаем метод без параметров:

ProcessTimerTick()

Если данные нужны, то добавляем один или оба нужных параметра:

ProcessTimerTick(Timer timer, DateTime dateTime)

Вызываем метод, соответственно, так:

void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
    ProcessTimerTick((Timer)sender, e.SignalTime);
}

Теперь, если нам нужно для какой-то цели вызвать этот метод, например, для модульного тестирования, то это делается легко и просто. И не нужна рефлексия.

Correct answer by Alexander Petrov on February 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP