我正在尝试找到创建系统的最佳方法,其中可以将事件源添加到管理器类中,然后管理器类将其事件重新分派给侦听器。具体来说,我有许多不同的输入源(键盘输入源,鼠标输入源,虚拟键盘输入源等),我想让开发人员在键盘输入源和输入上监听KeyDown事件。经理本身(从任何有效的输入源捕获此事件)。
很容易暴力破解解决方案,最终我创建了许多“调度”功能,只需在事件发生时重新调度事件,但我最终拥有数十个单行函数,我必须创建新函数每当将新事件添加到输入源接口时。
我考虑过使用lambdas,但是如果从管理器中删除了输入源,我需要一种解开事件的方法。我可以将lambda保存在字典中,由输入源键入,但许多事件具有不同的arg类,并且创建多个字典来实现这一点开始变得丑陋。
我想知道我是否缺少一些简单的方法来保持清洁,并保留我需要写下的额外代码。
作为参考,这里是我正在使用的对象的示例:
public interface IInputSource {}
public interface IKeyboardInputSource : IInputSource
{
event EventHandler<KeyboardEventArgs> KeyDown;
event EventHandler<KeyboardEventArgs> KeyUp;
}
public interface IMouseInputSource : IInputSource
{
event EventHandler<MouseEventArgs> MouseDown;
event EventHandler<MouseEventArgs> MouseUp;
}
public class InputManager : IKeyboardInputSource, IMouseInputSource
{
private List<IInputSource> InputSources;
//Event declarations from IKeyboardInputSource and IMouseInputSource
public void AddSource(IInputSource source)
{
InputSources.Add(source);
if (source is IKeyboardInputSource)
{
var keyboardSource = source as IKeyboardInputSource;
keyboardSource.KeyDown += SendKeyDown;
// Listen for other keyboard events...
}
if (source is IMouseInputSource)
{
// Listen for mouse events...
}
}
public void RemoveSource(IInputSource source)
{
if (source is IKeyboardInputSource)
{
var keyboardSource = source as IKeyboardInputSource;
keyboardSource.KeyDown -= SendKeyDown;
// Remove other keyboard events...
}
if (source is IMouseInputSource)
{
// Remove mouse events...
}
InputSources.Remove(source);
}
private void SendKeyDown(object sender, KeyboardEventArgs e)
{
if (KeyDown != null)
KeyDown(sender, e);
}
//Other "send" functions
}
答案 0 :(得分:1)
你看过Reactive Extensions(Rx)框架了吗?看起来它会满足您的要求,并为您提供丰富的功能/ lambda,如api来管理和处理事件。
Reactive Extensions(Rx)是一个库,用于使用可观察序列和LINQ样式查询运算符来编写异步和基于事件的程序
答案 1 :(得分:0)
这样的事情可能会有所帮助 - 这是一种通用方法,包括直接订阅事件或通过“接收器”界面
interface IInputSource<T> where T : EventArgs
{
event EventHandler<T> InputEvent;
}
interface IInputSink<in T> where T : EventArgs
{
void InputMessageHandler(object sender, T eventArgs);
}
internal class InputManager
{
private Dictionary<Type, object> _inputSources;
private Dictionary<Type, object> _inputSinks;
private Dictionary<Type, object> _events;
public void AddSource<T>(IInputSource<T> source) where T : EventArgs
{
_inputSources[typeof(T)] = _inputSources; //add source
_events[typeof(T)] = (EventHandler<T>)Dispatch; //register event for subscribers
source.InputEvent += Dispatch;
source.InputEvent += Dispatch2;
}
// Dispatch trough direct event subscriptions;
private void Dispatch<T>(object sender, T e) where T : EventArgs
{
var handler = _events[typeof(T)] as EventHandler<T>;
handler.Invoke(sender, e);
}
// Dispatch trough IInputSink subscriptions;
private void Dispatch2<T>(object sender, T e) where T : EventArgs
{
var sink = _inputSinks[typeof(T)] as IInputSink<T>;
sink.InputMessageHandler(sender, e);
}
//Subscription: Client should provide handler into Subscribe()
//or subscribe with IInputSink<MyEvent> implementation (Subscribe2())
public void Subscribe<T>(EventHandler<T> handler) where T : EventArgs
{
var @event = _events[typeof(T)] as EventHandler<T>;
_events[typeof(T)] = @event + handler;
}
public void Subscribe2<T>(IInputSink<T> sink) where T : EventArgs
{
_inputSinks[typeof(T)] = sink;
}
}
class XXXX : EventArgs
{
}
public class Sink: IInputSink<XXXX>
{
#region Implementation of IInputSink<in XXXX>
public void InputMessageHandler(object sender, XXXX eventArgs)
{
throw new NotImplementedException();
}
#endregion
public Sink()
{
var v = new InputManager();
v.Subscribe<XXXX>(GetInputEvent);
v.Subscribe2(this);
}
private void GetInputEvent(object sender, XXXX xxxx)
{
throw new NotImplementedException();
}
}