Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何强制使用订阅方法的事件_C#_Events_Event Handling_Runtime Error - Fatal编程技术网

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

C# 如何强制使用订阅方法的事件,c#,events,event-handling,runtime-error,C#,Events,Event Handling,Runtime Error,我正在制作一个图书馆,希望能在很多地方使用 在我的界面中,我有一个触发事件的方法。我缓存了自己,忘记订阅事件,在程序编译后出错。我想尝试推动用户订阅事件,以便在程序启动之前,如果没有订阅事件,他们会收到编译器错误 那有可能吗?或者,帮助和XML注释是否足以提及订阅活动的用户 我的界面看起来像: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Robot.Skol

我正在制作一个图书馆,希望能在很多地方使用

在我的界面中,我有一个触发事件的方法。我缓存了自己,忘记订阅事件,在程序编译后出错。我想尝试推动用户订阅事件,以便在程序启动之前,如果没有订阅事件,他们会收到编译器错误

那有可能吗?或者,帮助和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;
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用Robot.SkolaCa.BusinessObjects;
命名空间Robot.SkolaCa.FiskalPrinter
{
OnRacunSuccessEvent上的公共委托无效(对象发送方,OnRacunSuccessArgs eargs);
公开委托无效OnRacunErrorEvent(对象发送方,OnRacunErrorArgs eargs);
公开类onracunerrorgs:EventArgs
{
公共字符串错误消息{get;set;}
}
公共类onracunccessargs:EventArgs
{   
公共字符串成功消息{get;set;}
}
公共接口IFiskalPrinter
{
bool PresjekStanja();
bool DnevniIzvjestaj();
/// 
///请订阅所有活动!!!!
/// 
/// 
void Racun(Racun-Racun);
bool StornpRacuna(Racun Racun,int Brojfiskalnogkojissestornira);
void SetConfig(IPrinterConfig config);
OnRacunSuccess事件OnRacunSuccess事件;
事件OnRacunError事件OnRacunError事件;
}
}

您不能通过编程强制它,即您不能产生编译错误。如果这是一个抽象类,您可以执行诸如覆盖Dispose或检查事件调用程序以查找现有引用,甚至清除处理程序之类的操作,但对于接口,您只能做很少的事情。

您不能通过编程强制它,也就是说,您不能产生编译错误。如果这是一个抽象类,您可以执行诸如覆盖Dispose、检查事件调用者是否存在引用,甚至清除处理程序之类的操作,但对于接口,您所能做的很少。

嗯,您可以“强制”用户订阅事件(例如,如果这是一个单一事件或小数量,则必须订阅)

  • 您可以创建一个私有的默认构造函数
  • 您可以创建一个构造函数,该构造函数像参数一样接受将添加到事件中的委托
  • 如果类的用户传递的是
    null
    而不是
    delegate
    ,则可以引发异常,因此将获得运行时异常,而不是编译时异常
  • 在这种情况下,您的类的用户将没有其他方法,只需传递一个委托即可。 这是你喜欢的类型

    编辑

    还有另一个解决方案,imo,可以应用在这种情况下,就是使用面向方面的编程(我以前从未针对这个问题做过,所以这只是建议,请看一下)。 如果用属性标记类,并且在编译期间,方面检查代码将确定未传递任何委托,则可能会生成编译时错误

    但是,正如我所说的,我从来没有这样做过,所以你需要自己检查一下

    希望这能有所帮助。

    好吧,你可以“强制”用户订阅活动(例如,如果这是一个单独的活动,或者数量很小,必须订阅)

  • 您可以创建一个私有的默认构造函数
  • 您可以创建一个构造函数,该构造函数像参数一样接受将添加到事件中的委托
  • 如果类的用户传递的是
    null
    而不是
    delegate
    ,则可以引发异常,因此将获得运行时异常,而不是编译时异常
  • 在这种情况下,您的类的用户将没有其他方法,只需传递一个委托即可。 这是你喜欢的类型

    编辑

    还有另一个解决方案,imo,可以应用在这种情况下,就是使用面向方面的编程(我以前从未针对这个问题做过,所以这只是建议,请看一下)。 如果用属性标记类,并且在编译期间,方面检查代码将确定未传递任何委托,则可能会生成编译时错误

    但是,正如我所说的,我从来没有这样做过,所以你需要自己检查一下


    希望这能有所帮助。

    根据定义,活动是临时性的,即如果一个人想订阅,他/她就订阅,如果他/她不想订阅,那么这是他/她的权利。通过宣布一个活动,你说“如果有人感兴趣,我会通知他一些事件”。因此,强制订阅的整个想法是错误的

    但如果您需要强制使用者执行某些操作,则最好为类使用者声明一个共同接口,并使您的方法接收接口实现作为参数。例如:

    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,并且调用者无法订阅,则您将能够抛出运行时错误。这将使您的契约更加明确。您现在说的是“如果您不给我一个侦听器对象,我将不工作”

    然后,您可以创建(比如)代码分析或FxCop规则来检查noone是否使用空方法实现了接口

    等等

    但笑话是:如果有人想打破你的规则,他会的

    更新


    co接口解决方案可能更好,因为使用
    事件
    您不仅可以有0个订阅者,还可以有1000个订阅者。写XML注释说“请,验证您始终只有一个订阅者”怎么样?您知道,这很难验证。

    根据定义,事件是临时性的,即如果有一个订阅者想要,他/她订阅,如果没有-那是他/她的权利。通过宣布一个事件,你说“如果有人感兴趣,我会”