Laden...

Event-auslösende Methode über verschiedene Klassen aufrufen

Erstellt von ayka vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.363 Views
A
ayka Themenstarter:in
2 Beiträge seit 2019
vor 4 Jahren
Event-auslösende Methode über verschiedene Klassen aufrufen

Hallo zusammen,

ich habe eine Frage zu Events und hoffe, dass ihr mir weiterhelfen könnt. Ich muss auch dazu schreiben, dass ich mich erst seit kurzem mit C# befasse.

Ich habe nach dieser Anleitung einen Event programmiert ([Lösung] Problem mit EventHandler [==> fertige Code-Snippets inkl. Erklärung]) und das funktioniert auch soweit. Die event-auslösende Methode informiert den Eventhandler. Jetzt möchte ich aber auch aus einer anderen Klasse ein Event auslösen und der Eventhandler soll entsprechend reagieren. Leider klappt das nicht so, wie ich es mir vorstelle. Nachfolgend mein Code:

Klasse LogFile mit der event-auslösende Methode: Es soll nur einfache Textinformationen loggen.

     
class LogFile
    {
        //Event for log file change
        public event EventHandler LogEvent;
        protected virtual void MyLogEvent(EventArgs e)
        {
            EventHandler logEvent = LogEvent;
            if (logEvent != null)
            {
                logEvent(this, e);
            }
        }

        //Set list for text information and define counter
        private static List<string> LogSum = new List<string>();
        private static int count = 1;

        //After each call log file will be added and index increased
        public void AddLogFile (string logText)
        {          
            //Log number and text information
            LogSum.Add(count + ": " + logText);

            count++;

            //Activate event
            MyLogEvent(EventArgs.Empty);
        }

        public List<string> GetLogFile()
        {
            return LogSum;
        }
    }
 

Klasse MainForm mit dem Eventhandler: Die Log Informationen sollen hier vereinfacht in einer Textbox dargestellt weden.

 
    public partial class MainForm : Form
    {
        LogFile _log = new LogFile();
        Control _control;
        public static List<string> LogFiles = new List<string>();
        public MainForm()
        {
            InitializeComponent();
            _log.LogEvent += LogChanged;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            //do something
            _log.AddLogFile("Something made: 1");
            _control = new Control();
        }

        //Update log view
        public void LogChanged(object sender, EventArgs e)
        {
            //Get new log file
            LogFiles = _log.GetLogFile();


            //Write down to textbox
            TestTextBox.Text = null;
            foreach (string item in LogFiles)
            {
                TestTextBox.Text += item + "\r\n";
            }
            TestTextBox.Refresh();
        }
    }
 

Soweit funktioniert alles und „Something made: 1“ steht in der Textbox. Nachfolgend eine andere Klasse, der ebenfalls ein Logeintrag durchführt und somit ebenfalls ein Event auslösen soll.

 
    class Control
    {
        LogFile _log = new LogFile();
        public Control()
        {
            //do something
            _log.AddLogFile("Something made: 2");

        }
    }
 

In meiner Testtextbox steht trotzdem nur der erste Eintrag „Something made: 1“. Der zweite Eintrag kommt nicht, weil in der event-auslösenden Methode logEvent = null ist.

Warum steht bei logEvent beim Aufruf über eine andere Klasse null? Die Textinformation wird auf jeden Fall geloggt und ist vorhanden. Sie löst nur kein Event aus.

Vielen Dank für eure Tipps im voraus.

1.029 Beiträge seit 2010
vor 4 Jahren

Hi,

das ist recht einfach erklärt - aktuell besitzt du mit deinem Code 2 Instanzen der Klasse "LogFile" wo du nur eine bräuchtest.

Die erste wird in deiner Form erzeugt und an deren Event hängst du dich ran.
Die zweite wird im Control erzeugt - deren Event abonnierst du allerdings nirgends - deswegen kommt auch nirgends ein Event an.

Die einfachste Variante um das zu lösen wäre es wohl bei der Instanziierung der Klasse Control (control = new Control();) eine Referenz auf die Instanz der Klasse LogFile mitzugeben. (also: control = new Control(_log);)

LG

Noch einige Anmerkungen:
a) Logging sollte/muss man heute nicht mehr selbst bauen. Was immer du tust - gibt es schon fertig und besser. Serilog, NLog und zig andere Frameworks die auch entsprechende Standardschnittstellen bieten sind hier einen Blick wert
b) Deinen Code für das EventHandling solltest du noch mal anpassen.

  1. Die Methoden, die einen Event auslösen sollten gemäß gängiger Praxis mit "On" beginnen - also z.B. "OnLogEntryAdded"
  2. Als Tipp zur Schreibweise - dafür kann man auch einen Einzeiler einsetzen - z.B.

protected virtual void OnLogEntryAdded(EventArgs e)
        {
            LogEvent?.Invoke(this, e);
        }

16.807 Beiträge seit 2008
vor 4 Jahren

Du hast zwei Instanzen Deines Loggings.

PS:
Gibt 2019 keine große Notwendigkeit ein Loggingmechanismus selbst zu schreiben.
In .NET ist das absolute führende Framework hierzu serilog, das in allen Arten von .NET Applikation binnen weniger Minuten aufgesetzt ist.

/ Taipi88 war schneller.

A
ayka Themenstarter:in
2 Beiträge seit 2019
vor 4 Jahren

Danke euch beiden. Werde mir alle Vorschläge anschauen.