2012-05-30 31 views
0

我试图找到创建系统的最佳方法,即可以将事件源添加到管理器类,然后将其重新分派给侦听器。具体来说,我有许多不同的输入源(键盘输入源,鼠标输入源,虚拟键盘输入源等),我希望允许开发人员监听键盘输入源和输入上的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

我应该提到这前面 - 但我工作的项目不允许我使用任何第三方库,很遗憾。 –

+0

但是,您可以检查bbvcommon库中使用的代码,因为它是开源的,然后您可以将其复制并将其修改为您的代码。这是直接链接到源代码https://github.com/bbvcommon/bbv.Common – Jupaol

+0

好点。我会检查出来的! –

回答

1

你看的Reactive Extensions(Rx)的框架?看起来像你会问什么,并为你提供丰富的功能/ lambda像API来管理和处理事件。

无功扩展器(Rx)是构成使用观察序列和LINQ风格查询操作

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(); 
    } 
}