如何强制使用订阅方法事件

时间:2011-12-24 12:35:58

标签: c# events event-handling runtime-error

我正在制作一个图书馆,我希望这样可以在很多地方使用。

在我的界面中,我有一个触发事件的方法。我已经缓存自己忘记订阅事件并在程序编译后得到错误。我很乐意尝试推动用户订阅事件,以便在程序启动之前如果没有订阅事件就会遇到编译器错误。

这有可能吗?或者是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;
    }
}

3 个答案:

答案 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)

好吧,您可以“强迫”用户订阅该事件(例如,如果这是单个事件,或者数量很小,必须订阅)

  1. 您可以创建私有默认构造函数
  2. 您可以创建一个类似于参数的构造函数接受您将添加到事件中的代理。
  3. 如果您的班级用户通过null而不是delegate,则可以引发异常,因此您将获得运行时异常且无法编译时间
  4. 在这种情况下,您的班级用户将没有其他方式,只需传递一个委托。 你的类型建筑约束。

    修改

    还有另一个解决方案,imo,在这种情况下可以应用,是使用面向方面编程(我从来没有为此问题做过,所以这只是建议太看看) 。 如果使用属性标记类,则在编译期间,方面检查代码将确定没有传递委托,可以生成编译时错误

    但是,正如我所说,我从来没有为这类问题做过,所以你需要自己检查一下。

    希望这有帮助。

答案 2 :(得分:0)

您不能以编程方式强制它,即您不能产生编译错误。如果这是一个抽象类,你可以做一些事情,比如覆盖Dispose或检查现有引用的事件调用者,甚至清除你的处理程序,但是对于接口,你可以做的很少。