在C#中你可以设置事件的约束吗?

dbo*_*ski 7 c# events constraints

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

即我想要一个实现IPerson的对象"Employee"订阅一个事件处理程序,但另一个对象"Truck"实现了一个完全不同的接口来限制.开箱即用的任何实现正确方法模式的对象都可以订阅.

我该如何限制?

我问的原因是我正在实现Observer模式,但尝试使用C#Events.我有一个类似于MSDN的例子.

我关注的仍然是任何具有任何结构的对象(只要它包含正确的委托方法)可以在事件触发时执行.所以在上面的例子中,一个Employee可以实现对我的例子中的对象有意义的方法,但是然后任何人都可以在上面的例子中创建另一个类 - "truck",具有任何结构(只要它再次实现该方法)并且与主题事件联系起来...这绝对是对物体使用和良好设计的关注,也许我在这里非常挑剔,但这让我感到烦恼.

Ani*_*Ani 8

这是一个非常糟糕的主意.请不要这样做.

你想要保护什么?任何"敌对"类型都可以实现界面(如果他们看不到界面,因为它在你的项目内部,那么就没有理由不把事件放在内部),所以你的黑名单并不是那么好.更糟糕的是,这会使白名单上的类型变得更难 - 他们无法轻易地将侦听器委托给"近距离"相关类型的实例.即使使用闭包(通过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); }
Run Code Online (Sandbox Code Playgroud)


Eri*_*ert 7

在C#中你可以设置事件的约束吗?

不.

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

事件侦听器是与事件类型兼容的类型的委托的实例."类型"不是事件的听众.

即我想要一个实现IPerson的对象"Employee"订阅一个事件处理程序,但另一个对象"Truck"实现了一个完全不同的接口来限制.

"员工"对象不会首先听取事件.侦听事件的唯一事情是委托对象.

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

在编译时不可能阻止它,但如果你真的很想做这个奇怪的事情,你可以在运行时这样做.

为此,正如其他答案所述,您可以为事件创建加法器和卸载访问器方法,然后检查加法器,验证委托的接收者是您赞同的类型,并抛出异常如果不是.

但同样,这听起来像是一个非常糟糕的主意.由听众决定他们是否对该事件感兴趣,而不是由事件来源来审查其听众.用户可以合理地期望任何兼容类型的代表都可以监听任何可访问的事件.

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

  • 仅仅因为你无法想象为什么其他人应该订阅,并不意味着你需要限制它."一个成功的工具是用来做其作者的一些不可思议的工具." - 斯蒂芬C.约翰逊 (3认同)