Ошибка при поднятии пользовательского события

У меня есть класс, который будет писать журнал. Класс должен инициировать событие (при определенных обстоятельствах, не указанных ниже), которое будет использовано классом для реагирования на него. У меня есть код ниже, но как только я пытаюсь вызвать событие, я получаю сообщение об ошибке, как указано, что

В экземпляре объекта не задана ссылка на объект

Есть идеи, что мне не хватает?

//1. Class where event is registered
    public class LogEvent
    {
        public delegate void WriteLogEventHandler(object Sender, WriteLogEventArgs e);
        public event WriteLogEventHandler WriteLog;

        public class WriteLogEventArgs : EventArgs
        {
            public string Message { get; set; }

            public WriteLogEventArgs(string message) : base()
            {
                Message = message;
            }
        }

        //Raise the event.
        internal void OnWriteLog(WriteLogEventArgs e)
        {
             WriteLog(this, e);    //Error here.  Seems like WriteLog is null
        }

//2. Class where event is raised.
public class Logs
{
    public static void WriteLog(string message)
    {
        LogEvent.WriteLogEventArgs args = new LogEvent.WriteLogEventArgs(message);
        new LogEvent().OnWriteLog(args);
    }
}

//3. Class where event should be consumed
public class MyClass()
{
    private LogEvent _logEvent;
    public MyClass()
        {
            //Subscribe to event:
            _logEvent = new LogEvent();
            _logEvent.WriteLog += (sender, args) => { DoSomething(args.Message); };
        }

   public void DoSomething(string message)
   { ... }
}

1 ответ

Решение

Два вопроса:

  • Вы поднимаете событие независимо от того, подписался ли кто-либо на него. Не делай этого - ты получишь NullReferenceException если ты позвонишь WriteLog(this, e) когда WriteLog нулевой. В C# 6 этого легко избежать:

    WriteLog?.Invoke(this, e);
    
  • Вы подписываетесь на событие по другому LogEvent экземпляр, чем тот, который вызывает событие. Это больше проблема дизайна, чем что-либо еще - нет смысла для отдельного события журнала иметь список подписчиков. Вместо этого вы должны иметь Logger или аналогичный, который имеет подписчиков (через событие), то каждый LogEvent передается этим подписчикам. Вы бы создали один Logger, подпишитесь на него, затем позвоните WriteLog в том же случае.

Другие вопросы по тегам