2012-08-06 33 views
3

我有两个类,Input和“EventSystem”。 EventSystem是处理“内部应用程序事件”的内部(非系统相关)类。输入是一个依赖类(系统相关),处理键/按钮事件并将它们映射到关键事件和“EventSystem”。我会告诉你我目前是如何传递数据的,它在内部看起来很干净,但在外面很脏。有谁知道更好的方法 - 或更简单的方法 - 传递自定义值?向事件系统传递自定义数据/值

的EventSystem:

// Raisable Events 
public enum EventType { Action, Cancel }; 

// Base for custom arguments 
public class EventArguments 
    { 
     public double time; 

     public EventArguments(double _time) 
     { 
      time = _time; 
     } 
    } 


// Event Delegate (invoked on raise) 
public delegate void Event(EventArguments eventArgs); 

// full class 
static class EventSystem 
{ 
    private static Dictionary<EventType, Event> eventMapping = new Dictionary<EventType, Event>(); 

    public static void HookEvent(EventType eventType, Event _event) 
    { 
     if (eventMapping.ContainsKey(eventType)) 
     { 
      eventMapping[eventType] += _event; 
     } 
     else 
     { 
      eventMapping.Add(eventType, _event); 
     } 
    } 

    public static void RaiseEvent(EventType eventType, EventArguments args) 
    { 
     if (eventMapping.ContainsKey(eventType)) 
     { 
      eventMapping[eventType].Invoke(args); 
     } 
     else 
     { 
      // do nothing 
     } 
    } 
} 

我输入ARGS只是继承EventArguments。

// Inherits EventArguments (double time) and adds it's own, "bool pressed" 
class KeyInputArguments : EventArguments 
{ 
    public bool pressed; 

    public KeyInputArguments(double time, bool _pressed) : 
     base(time) 
    { 
     pressed = _pressed; 
    } 
} 

当一个键被按下它触发键(输入)的事件,则它检查以查看是否键被映射到内部事件,提高它。一个单独的类(Config)处理映射/绑定键到事件的所有配置。

// Raise on press 
EventSystem.RaiseEvent(eventType, new KeyInputArguments(time, true)); 
// [...] 
// Raise on release 
EventSystem.RaiseEvent(eventType, new KeyInputArguments(time, false)); 

最后,为了触发事件,我们必须注册的关键事件(这是“外部”代码)

// Hook our "Enter" function into the Action event 
EventSystem.HookEvent(EventType.Action, Enter); 

// [...] 

public void Enter(EventArguments eventArg) 
{ 
    if (((KeyInputArguments)eventArg).pressed == false) 
    { 
     Error.Break(); 
    } 
} 

一切都很好,直到我看到'我的C#和OOP编程知识有限,这是一个难看的结果

我无法更改Enter方法参数,因为事件委托明确需要EventArgum经济需求。 (即使KeyInputArguments继承它?)。我也不明白为什么要将eventArg投入到KeyInputArguments。

最后,我也试过这个(虽然我不喜欢那么多)

KeyInputArguments keyInputArguments = (KeyInputArguments)eventArg; 
      if (keyInputArguments.pressed == false) 

我需要自定义数据的原因是,我打算从多形式的输入,如游戏手柄的接收输入。这意味着我可以将系统相关数据(游戏手柄设备信息)处理为独立参数。这将系统相关数据限制在我的Input类中,同时将我的事件系统作为独立的内部使用。 我在做什么有更好的方法吗?

+1

你可以看看使用“as”操作符。 http://msdn.microsoft.com/en-us/library/cscsdfbt(v=vs.100).aspx – 2012-08-06 04:52:43

+0

不能直接回答你的问题,但你可以看看棱镜的事件聚合器,我认为做你需要什么http://msdn.microsoft.com/en-us/library/ff921122%28v=pandp.20%29.aspx – 2012-08-06 05:46:43

回答

2

将这个代码在项目中的某处:

public static class SomeClassName 
{ 
    public static T CastTo<T>(this object source) 
    { 
     return (T)source; 
    } 
} 

这使您可以编写

if(!eventArg.CastTo<KeyInputArguments>().pressed) 
    Error.Break(); 

我真的很喜欢这一点,因为它节约了留下来的东西正确的顺序。编写linq时这是特别好的。

在回答你的问题“即使KeyInputArguments继承它?”。这里的问题是你已经定义了一个使用基类的通用目的方法,它不知道继承类。您将需要对方法使用泛型来解决这一问题,例如,在事件类型传递作为一种通用的参数

public static void HookEvent<TEventType>(....) 
+0

我还没有研究仿制药呢。我会看看今天晚上我能改善什么! – 2012-08-06 14:34:30

0

我结束了混合MikeKulls回答“HookEvent”,并从朋友一些建议,并想出了此:

// Event types to raise. 
enum EventType { Action, Cancel }; 

// Base abstract class to use in the generic type field 
abstract class BaseEvent 
{ 
    public double time; 

    protected BaseEvent(double _time) 
    { 
     time = _time; 
    } 
} 

// Event delegate, T is a sub of BaseEvent that contains the data we need to send 
delegate void EventDelegate<T>(T eventClass) where T : BaseEvent; 

// Event class 
static class EventSystem 
{ 
    // EventClass is the storage of all the generic types and their mapping to an event delegate. 
    private static class EventClass<T> where T : BaseEvent 
    { 
     public static Dictionary<EventType, EventDelegate<T>> eventMapping = new Dictionary<EventType, EventDelegate<T>>(); 
    } 

    /// <summary> 
    /// Hooks an event to a delegate for use with EventSystem.RaiseEvent 
    /// </summary> 
    /// <typeparam name="T">Sub-class of BaseEvent that your delegate will be receiving</typeparam> 
    /// <param name="eventType">Type of event to hook to</param> 
    /// <param name="_event">The callback</param> 
    public static void HookEvent<T>(EventType eventType, EventDelegate<T> _event) where T : BaseEvent 
    { 
     if (EventClass<T>.eventMapping.ContainsKey(eventType)) 
     { 
      EventClass<T>.eventMapping[eventType] += _event; 
     } 
     else 
     { 
      EventClass<T>.eventMapping.Add(eventType, _event); 
     } 
    } 

    /// <summary> 
    /// Raises an event and calls any callbacks that have been hooked via HookEvent 
    /// </summary> 
    /// <typeparam name="T">The sub-class of BaseEvent you are sending</typeparam> 
    /// <param name="eventType">Type of event you are raising</param> 
    /// <param name="args">A subclass of BaseEvent containing the information to pass on</param> 
    public static void RaiseEvent<T>(EventType eventType, T args) where T : BaseEvent 
    { 
     if (EventClass<T>.eventMapping.ContainsKey(eventType)) 
     { 
      EventClass<T>.eventMapping[eventType].Invoke(args); 
     } 
     else 
     { 
      // do nothing 
     } 
    } 
} 

我设置输入象这样:

class KeyEvent : BaseEvent 
    { 
     public bool pressed; 

     public KeyEvent(double _time, bool _pressed) 
      : base(_time) 
     { 
      pressed = _pressed; 
     } 
    } 
// [...] 
// Key down 
EventSystem.RaiseEvent<KeyEvent>(eventType, new KeyEvent(time, true)); 
// Key up 
EventSystem.RaiseEvent<KeyEvent>(eventType, new KeyEvent(time, false)); 

我安装该处理程序/委托这样的:

EventSystem.HookEvent<KeyEvent>(EventType.Action, Enter); 
// [...] 
public void Enter(KeyEvent keyEvent) 
{ 
    if (keyEvent.pressed == false) 
    { 
     Error.Break(); 
    } 
} 
相关问题