确保事件永远不会有超过一个订阅者
Ensure event can never have more than one subscriber
我想确保特定事件永远不会有超过一个订阅者。在我的特殊情况下,拥有多个订阅者是没有意义的,如果这样做的话,可能会出现一些偷偷摸摸的问题。
旁注:特别是,我的处理程序(订阅者)必须是 async
并且在引发事件时我必须 await
它。原因是这是一个网络套接字包装 class,我在其中引发 TextReceived 事件,并且我不想在用户(订阅者)最后完成处理之前从套接字中读取更多数据TextReceived 事件(因为用户通常会向套接字写入一些回复,并且多个 in-flight 回调会导致冲突)。也许这种情况可以用另一种方式更好地解决(没有异步事件),而我正在尝试解决错误的问题。如果是,怎么办?
这是我想出的解决方案,但我想知道它是否是唯一的选择,或者是否可以进一步简化。
这是我的代码:
private TextReceivedAsyncHandler _textReceivedAsync;
public event TextReceivedAsyncHandler TextReceivedAsync
{
add
{
if (_textReceivedAsync != null)
throw new MultipleSubscribersNotAllowedException(eventName: nameof(TextReceivedAsync));
_textReceivedAsync = value;
}
remove
{
_textReceivedAsync = null;
}
}
这是限制多个订阅者的最短方法吗,或者你能提出更优雅的解决方案吗?我想过使用 public 委托 属性 而不是事件,但这并不能解决任何问题,因为无论如何委托都是多播的。
我仍然建议公开委托本身。是的,委托是多播的,它仍然可能引用多个方法。但是,事件的 语义 假定多个订阅者的可能性,并且限制这一点会让您的代码用户感到非常困惑。但是,如果您公开委托,则很明显只有一个 "subscriber" 是预期的。要防止使用 +=
语法,您可以这样做:
private Func<YourEventArgs, Task> _callback;
public Func<YourEventArgs, Task> Callback
{
set { _callback = value; }
}
确实,用户可能仍会使用多种方法传递委托:
Func<YourEventArgs, Task> delegateA = ...;
Func<YourEventArgs, Task> delegateB = ...;
Callback = delegateA + delegateB;
但是你的TextReceivedAsync
活动也是如此,我认为这是订阅者自己的问题。
如果您真的想要阻止多播委托,还有一个选项是:
private Func<YourEventArgs, Task> _callback;
public Func<YourEventArgs, Task> Callback
{
set
{
if (value != null && value.GetInvocationList().Length > 1) {
throw new Exception("...");
}
_callback = value;
}
}
我想确保特定事件永远不会有超过一个订阅者。在我的特殊情况下,拥有多个订阅者是没有意义的,如果这样做的话,可能会出现一些偷偷摸摸的问题。
旁注:特别是,我的处理程序(订阅者)必须是 async
并且在引发事件时我必须 await
它。原因是这是一个网络套接字包装 class,我在其中引发 TextReceived 事件,并且我不想在用户(订阅者)最后完成处理之前从套接字中读取更多数据TextReceived 事件(因为用户通常会向套接字写入一些回复,并且多个 in-flight 回调会导致冲突)。也许这种情况可以用另一种方式更好地解决(没有异步事件),而我正在尝试解决错误的问题。如果是,怎么办?
这是我想出的解决方案,但我想知道它是否是唯一的选择,或者是否可以进一步简化。
这是我的代码:
private TextReceivedAsyncHandler _textReceivedAsync;
public event TextReceivedAsyncHandler TextReceivedAsync
{
add
{
if (_textReceivedAsync != null)
throw new MultipleSubscribersNotAllowedException(eventName: nameof(TextReceivedAsync));
_textReceivedAsync = value;
}
remove
{
_textReceivedAsync = null;
}
}
这是限制多个订阅者的最短方法吗,或者你能提出更优雅的解决方案吗?我想过使用 public 委托 属性 而不是事件,但这并不能解决任何问题,因为无论如何委托都是多播的。
我仍然建议公开委托本身。是的,委托是多播的,它仍然可能引用多个方法。但是,事件的 语义 假定多个订阅者的可能性,并且限制这一点会让您的代码用户感到非常困惑。但是,如果您公开委托,则很明显只有一个 "subscriber" 是预期的。要防止使用 +=
语法,您可以这样做:
private Func<YourEventArgs, Task> _callback;
public Func<YourEventArgs, Task> Callback
{
set { _callback = value; }
}
确实,用户可能仍会使用多种方法传递委托:
Func<YourEventArgs, Task> delegateA = ...;
Func<YourEventArgs, Task> delegateB = ...;
Callback = delegateA + delegateB;
但是你的TextReceivedAsync
活动也是如此,我认为这是订阅者自己的问题。
如果您真的想要阻止多播委托,还有一个选项是:
private Func<YourEventArgs, Task> _callback;
public Func<YourEventArgs, Task> Callback
{
set
{
if (value != null && value.GetInvocationList().Length > 1) {
throw new Exception("...");
}
_callback = value;
}
}