【发布时间】:2019-04-06 03:14:45
【问题描述】:
我正在尝试创建一个事件处理程序,它将遍历相同类型的委托列表并在需要时调用它们。我最终想要的是一个“主”处理程序,它控制调用哪些子处理程序(这是用于实现默认事件处理的嵌套状态机,因此如果事件在嵌套级别中得到处理,请阻止它传播到更高级别)
我最简单的解决方案是只订阅“最深”的事件处理程序。但这并不是我真正想要的行为,我希望该处理程序的主体说明它是否真的“处理”了事件,如果没有,则调用下一个级别。
所以我的第二种方法是只有一个实际的事件订阅者。这依次遍历委托列表,并使用修改后的方法签名调用它们,如果它处理了事件,则返回一个布尔值。
我的 .NET 事件定义:
public static event SensorChangeHandler SensorChangedEvent;
public delegate void SensorChangeHandler(bool triggered);
public static void TriggerSensorChange(bool triggered)
{
SensorChangedEvent?.Invoke(triggered);
}
在我的“主处理程序”类中:
List<Func<bool, bool>> myChildHandlers = new List<Func<bool, bool>>();
public void AddChildHandler(Func<bool, bool> childHandler)
{
myChildHandlers.Add(childHandler);
}
public SensorChangeHandler GetMasterHandler()
{
return (bool sensorTriggered) =>
{
foreach(var handler in myChildHandlers)
{
if(handler(sensorTriggered))
{
// event handled, so break out of loop
return;
}
}
};
}
在我的调用类中:
MasterHandler sensorChangedMaster = new MasterHandler();
sensorChangedMaster.AddChildHandler((bool triggered) =>
{
if(triggered)
{
// do some stuff
return true;
}
else
{
// not handled
return false;
}
})
// the actual .NET event subscriber
SensorChangedEvent += sensorChangedMaster.GetMasterHandler();
如果我想做的只是响应 SensorChanged 事件,这可以正常工作。但我想让这种模式通用,即
MasterHandler sensorChanged = new MasterHandler<SensorChangeHandler>();
和
public class MasterHandler<THandler> {
...
List<Func<bool, THandlerArgs>> myChildHandlers = new List<Func<bool, THandlerArgs>>();
public void AddChildHandler(Func<bool, THandlerArgs> childHandler)
{
myChildHandlers.Add(childHandler);
}
public THandler GetMasterHandler()
{
return (THandlerArgs args) =>
{
foreach(var handler in myChildHandlers)
{
if(handler(args))
{
return;
}
}
};
}
}
我是使用泛型和反射的新手,我不清楚如何获取委托参数并将它们传递给处理程序。任何建议将不胜感激!
【问题讨论】:
-
您所描述的内容听起来像是责任链。 stackoverflow.com/questions/2635857/…
-
您能解释一下为什么不使用
add和remove事件访问器来实现这个模式吗? (我完全不明白你为什么要做这项工作,但如果你打算这样做,绕过我们在语言中投入的所有工具来帮助你做这件事似乎是不正当的。) -
我喜欢责任链,谢谢你的链接!这听起来确实像我想要完成的事情。 @EricLippert 这对我来说是一个学习练习,我想尝试实现一个非常适合 .NET 事件的状态机框架。我是 C# 新手,所以不太确定更改添加和删除访问器对我有什么帮助。我有一个单独的 AddChildHandler 方法的原因是我实际上不想订阅该事件,而是在 GetMasterHandler() 返回的委托中手动调用。我同意它很时髦,所以我愿意接受建议
标签: c#