C#: Возможно ли, чтобы мое приложение сообщило о событии, которое произошло внутри одного из моих других классов? - PullRequest
1 голос
/ 26 марта 2020

Простите, если я не объясняю это правильно, я новичок в программировании, и я не совсем уверен, как это называется, если это возможно.

Сначала позвольте мне объяснить несколько вещей о моем классе. Мы назовем этот класс TextStats. Класс TextStats создает таймер следующим образом:

 private Timer timer;

Позже эти значения устанавливаются на таймер при его инициализации:

timer = new Timer(1000);
timer.Elapsed += OnTimedEvent;
timer.AutoReset = true;
timer.Enabled = true;

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

    private void OnTimedEvent(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Timed event has fired!");
    }

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

Теперь, в основном классе программы, я создаю экземпляр, я думаю, он называется экземпляром для класса TextStats:

TextStats textStats = new TextStats();

Хорошо, теперь вот часть, которую я поставил в тупик на! Класс TextStats запускает событие таймера так, как я хочу, и будет запускать весь вид кода за кулисами из моего основного класса ... однако, я также хотел бы иметь возможность "делиться" событием таймера TextStats внутри моего main class.

Другими словами, мой класс TextStats по-прежнему запускает событие таймера каждую секунду, как и положено, но я также хотел бы как-то создать событие внутри моего основного класса, чтобы это событие таймера внутри моего Класс TextStats также будет запускать, или делиться, или вставлять, или присоединяться к ... как бы этот процесс ни назывался ... LOL.

Я предполагаю, что это будет что-то подобное в Engli sh форма:

share event OnTimedEvent from textStats and map it to this.TimedEvent;

public void TimedEvent()
{
   //Additional code to run with OnTimedEvent event from class TextStats
}

ОК, я постарался сделать это как можно более понятным. Так что извините за длинное объяснение. Есть ли способ сделать то, что я хочу? Я не хотел показывать весь свой код, потому что я просто запрыгнул, и я уверен, что все в порядке, я не хотел, чтобы люди слишком отвлекались, и просто хотел сосредоточиться на этом. Большое спасибо за попытку помочь!

Ответы [ 2 ]

1 голос
/ 26 марта 2020

То, что может быть прикреплено к событию, называется EventHandler. EventHandler s - это типы делегатов в C#, который представляет ссылку на другой метод.

В вашем случае вы можете создать ElapsedEventHandler делегат / ссылку на метод, который вы хотите присоединить к вашему timer.Elapsed событию в TextStats классе, затем вы можете присоединить его к событию таймера:

class TextStats
{
    public void AddToTimer(ElapsedEventHandler handler)
    {
        timer.Elapsed += handler;
    }
}

В вашем основном классе вы можете сделать это:

var textStats = new TextStats();
// By doing this, when the timer inside TextStats fires, both OnTimedEvent
// in TextStats class and AnotherOnTimedEvent in main class will be called.
textStats.AddToTimer(AnotherOnTimedEvent);

private void AnotherOnTimedEvent(object sender, ElapsedEventArgs e)
{
}

Когда вы вызываете AddToTimer(AnotherOnTimedEvent), он передает метод AnotherOnTimedEvent как ссылку на метод AddToTimer, в котором метод присоединен к timer.Elapsed как другой обработчик события.

Примечание

Это иллюстрирует концепцию того, как обработчик событий может быть передан в ваш класс и присоединен к timer.Elapsed. Тем не менее, есть лучшие решения, когда вы принимаете во внимание принципы проектирования.

Например, ваш основной класс не должен знать, TextStats использует таймер внутри, потому что это деталь реализации. Он должен знать, что TextStats запускает событие каждые 1 секунду. Поэтому лучший способ сделать это - позволить TextStats выставить другое событие, к которому может присоединиться ваш основной класс, а в вашем классе TextStats соединить два события, поэтому всякий раз, когда срабатывает таймер, ваше новое событие также срабатывает. ,

Примерно так:

class TextStats
{ 
    private System.Timers.Timer timer;

    public event EventHandler EventFiresEveryOneSecond;

    public TextStats()
    {
        timer = new System.Timers.Timer(1000);
        timer.Elapsed += OnTimedEvent;
        timer.AutoReset = true;
        timer.Enabled = true;
    }

    private void OnTimedEvent(object sender, ElapsedEventArgs e)
    {
        EventFiresEveryOneSecond?.Invoke(sender, e);
    }
}

В вашем основном классе:

var textStats = new TextStats();
textStats.EventFiresEveryOneSecond += AnotherOnTimedEvent;

private void AnotherOnTimedEvent(object sender, EventArgs e)
{
}
1 голос
/ 26 марта 2020

Вы хотите использовать одни и те же часы для обоих классов.

Существует как минимум два способа сделать это.

  1. Простой, но сложный для последующего рефакторинга: Позвоните TimedEvent из TextStats когда основная форма OnTimedEvent запущена.

Чтобы достичь этого, вам нужно сделать TextStats членом класса.

    // Make your TextStats as a class member.
    TextStats textStats = new TextStats();
    private void OnTimedEvent(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Timed event has fired!");
        textStats.TimedEvent();
    }
Введите часы в TextStats. Это немного сложно, но проще для рефакторинга.
        public class TextStats
        {
            readonly System.Windows.Forms.Timer _tmr;

            public TextStats( System.Windows.Forms.Timer tmr )
            {
                _tmr = tmr;
                tmr.Tick += TimedEvent;
            }

            private void TimedEvent( object sender, EventArgs e )
            {
                // Implementation here
            }
        }

// When instantiating class, put your timer into it
    TextStats _textStats;
    void YourMainFormConstructor(){

         // Timer initialization.
         _textStats = new TextStats( timer );
    }

...