Ошибка при поднятии пользовательского события
У меня есть класс, который будет писать журнал. Класс должен инициировать событие (при определенных обстоятельствах, не указанных ниже), которое будет использовано классом для реагирования на него. У меня есть код ниже, но как только я пытаюсь вызвать событие, я получаю сообщение об ошибке, как указано, что
В экземпляре объекта не задана ссылка на объект
Есть идеи, что мне не хватает?
//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
в том же случае.