C# 当一个事件有多个订阅服务器时,如何获取每个订阅服务器的返回值?
代码如下所示: 时钟:C# 当一个事件有多个订阅服务器时,如何获取每个订阅服务器的返回值?,c#,events,return-value,subscription,C#,Events,Return Value,Subscription,代码如下所示: 时钟: public class Clock { public event Func<DateTime, bool> SecondChange; public void Run() { for (var i = 0; i < 20; i++) { Thread.Sleep(1000); if (SecondChange != null)
public class Clock
{
public event Func<DateTime, bool> SecondChange;
public void Run()
{
for (var i = 0; i < 20; i++)
{
Thread.Sleep(1000);
if (SecondChange != null)
{
//how do I get return value for each subscriber?
Console.WriteLine(SecondChange(DateTime.Now));
}
}
}
}
日志时钟:
public class LogClock
{
public static bool WriteLogEntry(DateTime now)
{
Console.WriteLine(now.ToShortTimeString() + " Log");
return false;
}
}
要运行代码,请执行以下操作:
var theClock = new Clock();
theClock.SecondChange += DisplayClock.TimeHasChanged;
theClock.SecondChange += LogClock.WriteLogEntry;
theClock.Run();
其他问题是:
- 每个订阅者返回一个值是否是一种良好的做法
- 将Action/Func声明为事件返回类型而不是手动声明委托是否是一种良好的做法
委托.GetInvocationList
if (SecondChange != null)
{
DateTime now = DateTime.Now;
foreach (Delegate d in SecondChange.GetInvocationList())
{
Console.WriteLine(d.DynamicInvoke(now));
}
}
使用Action/Func而不是手动声明委托是否是一种好的做法
对。但我要指出,最好的做法是事件使用
EventHandler
而不是Func
EventHandler
不支持返回值,但有一些.NET事件具有返回值,这在某种程度上是合理的。我认为最好在自定义代码< > Engasgs< /Cord>子类中使用一个可设置的属性,作为您的<代码> t>代码>。这就是我们在KeyEventArgs.Handled
中看到的模式。通过这种方式,您可以使用EventHandler
,订阅者也可以通过获取和设置此属性来在有限的范围内协调他们的响应。我认为使用Action/Func而不是委托是非常好的
但事件不应该这样使用。
它们是在不确定的时间点触发的,所以您不知道所有的参数
您真正需要的可能是:
var theClock = new Clock();
theClock.AddSecondsSubscriber(new DisplayClock());
theClock.AddSecondsSubscriber(new LogClock());
theClock.RunAndExecuteVisitors( theBoolResultYouNeed => Console.WriteLine(theBoolResultYouNeed) );
不同意。(objectsender,EventArgs e)模式充满了微妙的优点。在这里可以看到这两个公认的答案:发送方args模式的另一个优点是,如果您添加额外的数据,您只需向arg类添加一个元素,并提供额外的数据,而不会破坏现有代码。如果您声明自己的委托接受单个参数,任何添加的数据都将中断所有客户端。这甚至不需要创建一个新的子类。
var theClock = new Clock();
theClock.AddSecondsSubscriber(new DisplayClock());
theClock.AddSecondsSubscriber(new LogClock());
theClock.RunAndExecuteVisitors( theBoolResultYouNeed => Console.WriteLine(theBoolResultYouNeed) );