Ну, на мой взгляд, события и интерфейсы, которые вы показали, являются двумя сторонами одной медали (по крайней мере, в контексте, который вы описали), но на самом деле это две стороны этого.
Я думаю о событиях так: «Мне нужно подписаться на ваше событие, потому что мне нужно, чтобы вы сообщали мне, когда с вами что-то случится».
Принимая во внимание, что интерфейсом является «Мне нужно вызвать метод для вас, чтобы сообщить вам, что со мной что-то случилось».
Это может звучать так же, но это отличается от того, кто говорит, в обоих случаях говорит ваш "мастер-класс", и в этом вся разница.
Обратите внимание, что если у ваших подчиненных классов есть доступный метод, который подходит для вызова, когда что-то происходит в вашем мастер-классе, вам не нужно, чтобы подчиненный класс содержал код для его подключения, вы можете легко это в вашем методе CreateSlaveClass:
SlaveClass sc = new SlaveClass();
ChangeHappenedEvent += sc.ChangeHappened;
return sc;
Это будет в основном использовать систему событий, но пусть код MasterClass будет выполнять всю передачу событий.
Объекты SlaveClass живут так же долго, как класс singleton? Если нет, то вам нужно обработать случай, когда они устареют / больше не нужны, как в приведенном выше случае (в основном как у вас, так и у меня), вы держите ссылку на эти объекты в вашем MasterClass, и, таким образом, они никогда не будет иметь право на сборку мусора, если вы не удалите эти события принудительно или не зарегистрируете интерфейсы.
Чтобы решить проблему с SlaveClass, который не живет так долго, как MasterClass, вы столкнетесь с той же проблемой связи, как вы также отметили в комментарии.
Один из способов «обработки» (обратите внимание на кавычки) может заключаться в том, чтобы на самом деле не ссылаться непосредственно на правильный метод объекта SlaveClass, а вместо этого создать объект-обертку, который будет внутренне вызывать этот метод. Преимущество этого состоит в том, что объект-оболочка может использовать объект WeakReference для внутреннего использования, так что, как только ваш объект SlaveClass пригоден для сборки мусора, он может быть собран, а затем, когда вы в следующий раз попытаетесь вызвать для него правильный метод, заметит это, и поэтому вам придется вычистить.
Например, вот так (и здесь я печатаю без использования IntelliSense Visual Studio и компилятора, пожалуйста, примите значение этого кода, а не синтаксис (ошибки).)
public class WrapperClass
{
private WeakReference _Slave;
public WrapperClass(SlaveClass slave)
{
_Slave = new WeakReference(slave);
}
public WrapperClass.ChangeHappened()
{
Object o = _Slave.Target;
if (o != null)
((SlaveClass)o).ChangeHappened();
else
MasterClass.ChangeHappenedEvent -= ChangeHappened;
}
}
В вашем MasterClass вы бы сделали что-то вроде этого:
SlaveClass sc = new SlaveClass();
WrapperClass wc = new WrapperClass(sc);
ChangeHappenedEvent += wc.ChangeHappened;
return sc;
Как только объект SlaveClass будет собран, следующий вызов (но не раньше этого) из вашего MasterClass в обработчики событий для информирования их об изменении, все те оболочки, которые больше не имеют объекта, будут удалены.