我正在制作一个图书馆,我希望这样可以在很多地方使用。
在我的界面中,我有一个触发事件的方法。我已经缓存自己忘记订阅事件并在程序编译后得到错误。我很乐意尝试推动用户订阅事件,以便在程序启动之前如果没有订阅事件就会遇到编译器错误。
这有可能吗?或者是HELP和XML注释足以提及用户订阅事件。
我的界面如下:
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;
}
}
答案 0 :(得分:3)
根据定义,事件是兼性的,即如果有人想要,他/她订阅,如果没有 - 那么这是他/她的权利。通过宣布一个事件,你说'如果某人有兴趣,我会通知他一些事件'。因此,强制订阅的整个想法是错误的。
但是如果你需要强迫消费者做某事,你最好为你的类消费者声明一个共同接口,并使你的方法接收接口实现作为参数。例如:
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规则来检查没有人用空方法实现实现接口。
等等......
但是,这个笑话是:如果有人想破坏你的规则,他会。<强>更新强>
协同接口解决方案可能更好,因为使用event
,您不仅可以拥有0个订阅者,还可以拥有1000个订阅者。怎么样写XML评论说'请,确认你总是只有一个订阅'?你知道,这很难验证。
答案 1 :(得分:1)
好吧,您可以“强迫”用户订阅该事件(例如,如果这是单个事件,或者数量很小,必须订阅)
null
而不是delegate
,则可以引发异常,因此您将获得运行时异常且无法编译时间。 在这种情况下,您的班级用户将没有其他方式,只需传递一个委托。 你的类型建筑约束。
修改强>
还有另一个解决方案,imo,在这种情况下可以应用,是使用面向方面编程(我从来没有为此问题做过,所以这只是建议太看看) 。 如果使用属性标记类,则在编译期间,方面检查代码将确定没有传递委托,可以生成编译时错误。
但是,正如我所说,我从来没有为这类问题做过,所以你需要自己检查一下。
希望这有帮助。
答案 2 :(得分:0)
您不能以编程方式强制它,即您不能产生编译错误。如果这是一个抽象类,你可以做一些事情,比如覆盖Dispose或检查现有引用的事件调用者,甚至清除你的处理程序,但是对于接口,你可以做的很少。