1

Forgive me if I'm not explaining this correctly, I'm new to programming and I'm not exactly sure what it's called of if it's possible.

First let me explain a few things about my class. We'll call this class TextStats. The TextStats class creates a timer like this:

 private Timer timer;

Later, these values are set to the timer when it is Initialized:

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

Then I have an event inside my class that's fired every second, like this:

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

I'll be adding code to it later on, but basically I'm trying to refactor and clean up some code that's in my main class..

Now, in the program's main class, I'm creating an instance, I guess it's called an instance, to the TextStats class:

TextStats textStats = new TextStats();

OK, now here is the part I'm stumped on! The TextStats class fires the timer event like I want, and will run all the code sort of behind the scenes from my main class.... however, I'd like to also be able to "share" TextStats' timer event inside my main class.

So in other words, my TextStats class still fires the timer event every second like it should, but I'd also like to somehow create an event inside my main class, that the timer event inside my TextStats class will also fire, or share, or piggyback off of, or be attached to... whatever the process is called... LOL.

I imagine it would be something like this in English form:

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

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

OK, I've tried to make that as clear as possible. So sorry for the long explanation. Is there someway to do what I want? I didn't want to show all my code, as I just kind of jumped right in and I'm sure everything's a mess, I didn't want people getting too distracted and just wanted to focus on this one thing. Thank you so much for trying to help!

Jeremy McCloud
  • 163
  • 1
  • 8
  • You want a clock share between classes. One way is using [dependency injection](https://stackoverflow.com/questions/130794/what-is-dependency-injection) on both classes. – Louis Go Mar 26 '20 at 01:58

2 Answers2

1

You want to share the same clock for both class.

There are at least two way to do it.

  1. Easy way but hard to refactor later: Call TimedEvent of TextStats when main form OnTimedEvent fired.

To achieve it, you need to make TextStats as a class member.

    // 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();
    }
  1. Inject an clock into TextStats. It's a bit complex but easier for refactoring.
        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 );
    }

Louis Go
  • 2,213
  • 2
  • 16
  • 29
1

What can be attached to an event is called an EventHandler. EventHandlers are delegate types in C#, which represents the reference to another method.

In your case, you could create an ElapsedEventHandler delegate / reference to the method you want to attach to your timer.Elapsed event into TextStats class, then you could attach it to the timer event:

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

In your main class, you can do this:

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)
{
}

When you call AddToTimer(AnotherOnTimedEvent), it passes AnotherOnTimedEvent method as a reference to the AddToTimer method, in which the method is attached to timer.Elapsed as another event handler.

Note

This illustrates the concept of how an event handler could be passed into your class, and attached to timer.Elapsed. However, there are better solutions when you take design principles into consideration.

For example, your main class shouldn't know TextStats uses a timer internally, because that's an implementation detail. What it should know, is TextStats fires an event in every 1 seconds. So the better way of doing this is to let TextStats to expose another event which your main class can attach to, and in your TextStats class, hook up the two events, so whenever the timer ticks, your new event also fires.

Something like this:

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);
    }
}

In your main class:

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

private void AnotherOnTimedEvent(object sender, EventArgs e)
{
}
weichch
  • 9,306
  • 1
  • 13
  • 25
  • Hi Weichch! Thank you for your response and suggesting alternative way to handle this when taking design principles in to consideration. Haven’t even thought about this. – Jeremy McCloud Mar 26 '20 at 12:26