События по определению являются факультативными, то есть, если кто-то хочет, он / она подписывается, если нет - тогда это его / ее право. Объявляя о событии, вы говорите: «Если кому-то интересно, я сообщу ему о каком-либо событии». Поэтому сама идея принудительного подписки неверна.
Но если вам нужно заставить потребителей что-то делать, вам лучше объявить соинтерфейс для ваших потребителей класса и заставить ваши методы получать реализации интерфейса в качестве аргументов. Например:
public interface IFiskalPrinterConsumer
{
void OnRacunSuccess(string successMessage);
void OnRacunError(string errorMessage);
}
public interface IFiskalPrinter
{
bool PresjekStanja();
bool DnevniIzvjestaj();
void Racun(Racun racun, IFiskalPrinterConsumer consumer);
bool StornpRacuna(Racun racun, int brojFiskalnogKojiSeStornira);
void SetConfig(IPrinterConfig config);
}
Таким образом, вы сможете генерировать ошибки времени выполнения, если вызывающий абонент принимает значение NULL как consumer
, и вызывающий не сможет не подписаться. Это сделает ваш контракт более понятным. Теперь вы говорите: «Я не пойду на работу, если вы не дадите мне объект слушателя».
Затем вы можете создать, скажем, правила Code Analysis или FxCop, чтобы проверить, что никто не реализует интерфейс с пустыми реализациями методов.
И так далее ...
Но шутка такова: если кто-то хочет нарушить ваши правила, он сделает это.
UPDATE
Решение для совместного интерфейса может быть даже лучше, потому что с event
вы можете иметь не только 0 подписчиков, но и 1000 подписчиков. Как насчет написания комментариев XML со словами «пожалуйста, убедитесь, что у вас всегда есть ровно одна подписка»? Вы знаете, это довольно сложно проверить.