I am making one library which I hope so is going to be used at many places.
In my interface I have a method which triggers events. I have cached myself that forget to subscribe to the events and get error after program has compiled. I would love to try to push users to subscribe to the events so that they get compiler errors before a program starts if there is no subscription to the events.
Is that possible at all? Or is HELP and XML comments just enough to mention a user to subscribe to an event.
My interface looks like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Robot.SkolaCa.BusinessObjects;
namespace Robot.SkolaCa.FiskalPrinter
{
public delegate void OnRacunSuccessEvent(object sender, OnRacunSuccessArgs eargs);
public delegate void OnRacunErrorEvent(object sender, OnRacunErrorArgs eargs);
public class OnRacunErrorArgs : EventArgs
{
public string ErrorMessage { get; set; }
}
public class OnRacunSuccessArgs : EventArgs
{
public string SuccesMessage { get; set; }
}
public interface IFiskalPrinter
{
bool PresjekStanja();
bool DnevniIzvjestaj();
/// <summary>
/// PLEASE SUBSCRIBE TO ALL EVENTS !!!!
/// </summary>
/// <param name="racun"></param>
void Racun(Racun racun);
bool StornpRacuna(Racun racun, int brojFiskalnogKojiSeStornira);
void SetConfig(IPrinterConfig config);
event OnRacunSuccessEvent OnRacunSuccess;
event OnRacunErrorEvent OnRacunError;
}
}
Events by definition are facultative, i.e. if one wants, he/she subscribes, if not – then it’s his/her right. By declaring an event, you say ‘If someone is interested, I will notify him about some event’. Therefore, the whole idea of forcing subscriptions is wrong.
But if you need to force consumers do something, you’d better declared a co-interface for your class consumers and make your methods receive interface implementations as arguments. For example:
This way you’ll be able to throw run-time errors if the caller passes null as
consumer, and the caller won’t be able to not subscribe. This will make your contract more clear. You’re now saying ‘I’m not going to work if you won’t give me a listener object’.Then you might create, say, Code Analysis or FxCop rules to check that noone implements the interface with empty method implementations.
And so on…
But the joke is: if someone wants to break your rules, he will.
UPDATE
The co-interface solution might be even better, because with
eventyou can have not only 0 subscribers, but also 1000 subscribers. How about writing XML comments saying ‘please, verify that you always have exactly one subscription’? You know, that’s quite difficult to verify.