Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Issues with message logging class – Class is not handling event when triggered outside of main Form

I’ve made a class Logging which has the event Logging.Send() triggers an event that delivers a string message to any subscribed classes.

In this case I’m using this method Logging.Send(string message, ELogType type); which triggers the event Logs , which are then listened to by my main Form, which appends the message to a RichTextBox that acts as my text log depending on the message’s type.

My main issue is that this Logging.Send method only sends its message to the log when called in my main Form class. If I call it in another class, for the sake of the example let’s call it Controller, it triggers the event but the subscribing Form does not seem to receive it. What did do wrong?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Here’s an example of my issue:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

public enum ELogType { Primary, Simple, Extra, Readout, Debug }

public class Logging
{

    public Logging() { }

    public event EventHandler<LoggerMessageArgs> Log;

    public bool PostPrimaryLogs = true,
        PostSimpleLogs = true,
        PostExtraLogs = false,
        PostReadoutLogs = false,
        PostDebugLogs = false;

    public void Send(string message)
    {
        Send(message, ELogType.Primary);
    }

    public void Send(string primaryMessage, string simpleMessage)
    {
        Send(new[] { primaryMessage, simpleMessage }, new[] { ELogType.Primary, ELogType.Simple });
    }

    public void Send(string message, ELogType type)
    {
        Console.WriteLine("sendtest"); //to check that the send event was happening.
        if ((type == ELogType.Primary && PostPrimaryLogs == true) //is there some way to avoid this giant if statement here?
        || (type == ELogType.Simple && PostSimpleLogs == true)
        || (type == ELogType.Extra && PostExtraLogs == true)
        || (type == ELogType.Readout && PostReadoutLogs == true)
        || (type == ELogType.Debug && PostDebugLogs == true))
        Log?.Invoke(this, new LoggerMessageArgs(message, type));
    }

    public void Send(string[] messages, ELogType[] types) 
    {
        if (messages.Length == types.Length)

        for (int i = 0; i < messages.Length; i++) 
        {
                Send(messages[i], types[i]);
        }
    }
}

public class LoggerMessageArgs
{
    public string Message { get; }

    public ELogType LogType { get; }

    public LoggerMessageArgs(string message)
    {
        Message = message;
        LogType = ELogType.Primary;
    }

    public LoggerMessageArgs(string message, ELogType logType)
    {
        Message = message;
        LogType = logType;
    }
}

public class Controller
{
    Logging Logger = new Logging();

    public async Task DoControl()
    {
        Logger.Send("beginning doControl", ELogType.Primary);
        await Task.Delay(1000); //do work
        Logger.Send("finished doControl", ELogType.Primary);
        return Task.CompletedTask;
    }
}

public partial class Form1: Form
{
    Logging Logger = new Logging();

    //needs an additional RichTextBox LogTextBox, and a RichTextBox SimpleLogTextBox. The simple log box isn't super important to the issue at hand. It's mostly used as a status indicator.

    Form1()
    {
        InitializeComponent();
        Logger.Log += (sender, e) => 
        {
            Action action = () =>
            {
                if (e.LogType == ELogType.Primary || e.LogType == ELogType.Debug || e.LogType == ELogType.Extra || e.LogType == ELogType.Readout)
                {
                    LogTextBox.AppendText($@"{DateTime.Now:hh\:mm\:ss\.ffff}: {e.Message}{Environment.NewLine}");
                    LogTextBox.SelectionStart = LogTextBox.Text.Length;
                    LogTextBox.ScrollToCaret();
                }
                if (e.LogType == ELogType.Simple)
                {
                    SimpleLogTextBox.AppendText($@"{e.Message}{Environment.NewLine}");
                    SimpleLogTextBox.SelectionStart = SimpleLogTextBox.Text.Length;
                    SimpleLogTextBox.ScrollToCaret();
                }
            };

            if (LogTextBox.InvokeRequired)
            {
                LogTextBox.Invoke(action);
            }

            else
            {
                action();
            }
        };
    }

    private void TestButton_Click(object sender, EventArgs e)
    {
        Logger.Send(new string[] { "Form Primary Log Test", "Form Simple Log Test" }, new ELogType[] { ELogType.Primary, ELogType.Simple }); //logs come back from this one
        Controller.DoControl() //no logs come back from this one.        
    }
}        

With this code, I get the string "{datetime} Form Primary Test Log" in the primary log, but complete radio silence from DoControl.

How do I fix this?

Thank you.

>Solution :

The problem is that the main form attaches only to the event of its own instance of the logger, but the other forms create other instances.


One possible solution is to make your event static, so that there is only one instance of the event, even if you create several instances of the logger.

public static event EventHandler<LoggerMessageArgs> Log;

Another solution is to make the logger a singleton.

public class Logging
{
    public static readonly Logging Instance = new();

    private Logging() { } // Hide the constructor.
}

You can get the only instance with:

Logging Logger = Logging.Instance;

Or use it directly:

Logging.Instance.Send("beginning doControl", ELogType.Primary);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading