在C#中,您可以对事件设置约束吗?

在C#中,您可以对事件设置约束吗?,c#,events,constraints,C#,Events,Constraints,我想根据它们实现的接口限制可以订阅特定事件的类型 也就是说,我希望实现IPerson的对象“Employee”订阅事件处理程序,但另一个实现完全不同接口的对象“Truck”将受到限制。现成的任何实现正确方法模式的对象都可以订阅 我如何限制这一点 我问这个问题的原因是我正在实现观察器模式,但试图用C#Events实现。我有一个类似的例子 不过,我关心的是,当事件触发时,任何具有任何结构的对象(只要它包含正确的委托方法)都可以执行。因此,在我上面的示例中,一名员工可以实现对我示例中的对象有意义的方法

我想根据它们实现的接口限制可以订阅特定事件的类型

也就是说,我希望实现IPerson的对象“Employee”订阅事件处理程序,但另一个实现完全不同接口的对象“Truck”将受到限制。现成的任何实现正确方法模式的对象都可以订阅

我如何限制这一点

我问这个问题的原因是我正在实现观察器模式,但试图用C#Events实现。我有一个类似的例子


不过,我关心的是,当事件触发时,任何具有任何结构的对象(只要它包含正确的委托方法)都可以执行。因此,在我上面的示例中,一名员工可以实现对我示例中的对象有意义的方法,但在我上面的示例中,任何人都可以使用任何结构(只要它再次实现该方法)创建另一个类——“truck”,并与主题事件关联。。。这显然是对对象使用和良好设计的更多关注,也许我在这里吹毛求疵,但这让我很困扰。

我无法想象为什么需要这个,乍一看我觉得有点凌乱,但无论如何,您可以将此限制逻辑封装在事件持有者本身中,并公开
订阅(委托处理程序)
订阅事件而不是公开公共事件本身

class EventHolder
{
  private event EventHandler<NewUpdateEventArgs> NewUpdate;

  public void SubscribeForNewUpdates(object subscriptionOwner, 
                                     Action<NewUpdateEventArgs> callback) 
  {
     if (subscriptionOwner.GetType() == ... or subscriptionOwner is ...)
     {
        this.NewUpdate += .. subscribe callback
     }
  }
 }
类事件持有者
{
私有事件处理程序NewUpdate;
public void subscriptbefornewupdates(对象subscriptionOwner,
操作(回调)
{
如果(subscriptionOwner.GetType()==…或subscriptionOwner是…)
{
this.NewUpdate+=…订阅回调
}
}
}

这真是个坏主意。请不要这样做

你到底想保护什么?任何“敌对”类型都可以实现该接口(如果他们看不到该接口,因为它是项目内部的,那么就没有理由不将该事件也设置为内部的),因此您的黑名单并没有得到很好的实施。更糟糕的是,这使得白名单上的类型更加困难——它们无法轻松地将侦听器委托给“close”相关类型的实例。即使使用闭包(通过lambda/anonymous方法)也可能会突然中断订阅,“呈现”订阅对象可能会成为(黑名单)编译器生成的类的实例

这是一种很差的安全机制,它不提供编译时安全性。它不能很好地将坏人拒之门外,也使好人的生活变得困难

无论如何,这是可能的-您需要为事件使用自定义实现并验证每个订阅请求

//Please don't do this.

private EventHandler myEventField = delegate { };

// Add synchronization if required.
public event EventHandler MyEvent
{
   add
   {
      if(value.Target is IPerson)
        myEventField += value;

      else throw new ArgumentException("Subscriber must implement IPerson", "value");
   }

   remove { myEventField -= value; }
}


private void RaiseMyEvent() { myEventField(this, EventArgs.Empty); }
在C#中,您可以对事件设置约束吗

没有

我想根据它们实现的接口限制可以订阅特定事件的类型

事件侦听器是与事件类型兼容的委托的实例。“类型”不是事件的侦听器

也就是说,我希望实现IPerson的对象“Employee”订阅事件处理程序,但另一个实现完全不同接口的对象“Truck”将受到限制

“employee”对象首先不会侦听事件。侦听事件的唯一对象是委托对象

你是说你只想接受那些恰好是特定类的实例方法的方法的委托吗?这是一件非常奇怪的事情,我建议您不要尝试这样做

在编译时不可能防止这种情况发生,但如果您真的下定决心要做这种奇怪的事情,您可以在运行时做

为此,正如其他答案所指出的,您可以为事件创建adder和remover访问器方法,然后在adder中进行检查,以验证委托的接收者是否属于您认可的类型,如果不是,则引发异常

但这听起来又是一个非常糟糕的主意。由侦听器决定他们是否对事件感兴趣,而不是由事件源检查其侦听器。用户有合理的期望,任何可访问的事件都可以被任何兼容类型的委托监听


也许你可以解释为什么你想做这件奇怪的事;可能有更好的方法来实现您的目标。

听起来您想使用观察者模式,而不是事件。有一些有趣的答案可能会有所帮助。这是为了什么?出于好奇?Matt这正是我正在做的,但是我想用C#events作为持有者来实现该模式,而不是一个类型列表,遍历并调用该方法来通知。你是在暗示将C#Events纳入这个模式不是一件好事吗?@dbobrowski:对不起,我找不到观察者模式和你在问题中提出的问题之间的任何关系,你能再详细说明一下吗?请看我对上面Matt的回答-事件不适合观察者吗?我不想让任何人订阅。嗯。。。所以在阅读你的回复时,你似乎觉得这是个坏主意,而且很奇怪。我理解正确吗?@dbobrowski:是的。你为什么要这样做?出版报纸的编辑可以选择出版或不出版,但通常不决定谁不能订阅。订阅者不控制发布计划,但可以决定是否订阅。这就是人们期望出版商和订阅者之间的关系;改变这种关系是一件令人惊讶且不同寻常的事情,所以我想你会有一个非常令人信服的理由这么做。@dbobrowski每个系统,包括.NET和C#语言,都是为了支持可以解决你可能遇到的大多数问题的常见场景而设计的。如果你尝试