c# - 将自定义数据/值传递到事件系统

标签 c# .net

我有两个类,Input 和“EventSystem”。 EventSystem 是处理“内部应用程序事件”的内部(非系统相关)类。 Input 是一个依赖类(依赖于系统)并处理键/按钮事件并将它们映射到键事件和“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
        }
    }
}

我的输入参数简单地继承了 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) 处理映射/绑定(bind)键到事件的所有配置。

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

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

// 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 方法参数,因为事件委托(delegate)明确需要 EventArguments。 (即使 KeyInputArguments 继承了它?)。我也不明白为什么将 eventArg 转换为 KeyInputArguments 需要这么多时间。

最后,我也尝试了这个(虽然我不太喜欢)

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

我需要自定义数据的原因是我计划接收来自多种输入形式的输入,例如游戏 handle 。这意味着我可以将系统相关数据(游戏 handle 设备信息)处理成独立的参数。这将依赖于系统的数据限制在我的输入类中,同时在内部利用我的事件系统作为独立的。 我正在做的事情有更好的方法吗?

最佳答案

将这段代码放在你项目的某个地方:

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>(....)

关于c# - 将自定义数据/值传递到事件系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11822644/

相关文章:

c# - 是否可以引用未在 .nswag 文件中定义的 C# 类?

c# - 如何从数据库刷新 ObjectContext 缓存?

C#静态方法问题

c# - 如何使用 LINQ 返回不同的记录

c# - javascript 请求.QueryString

.net - 为什么事件在 .NET 中没有返回类型?

c# - 如何使用 LINQ 删除数组中的重复元素?删除重复的元素?

c# - 比 DialogResult 包含更多信息的自定义 ShowDialog

c# - 我应该在执行 SQL 语句之前从中删除空格吗?

c# - 更高效地将 WinForms 转换为 WPF 或将 WPF 转换为 Winforms