繁体   English   中英

在C#中创建简单的全局事件系统的最佳方法是什么?

[英]What is the best way to create a simple global event system in C#?

我想在C#中创建一个快速事件系统,但我不确定接近它的最佳方法。 以下是我希望它的工作方式:

信使

这是我希望存储所有事件的地方。 该类看起来像这样:

public static class Messenger
{
    // This event would have a few params, like GameState, Ammo, and Lives, or something
    public static GameStateMessage OnGameStateChanged;

    // This event could be generic, with no args
    public static Message OnGameStarted;
}

认购

我希望通过这样的方式能够订阅这些消息:

// Handler, which will be passed to the event
private void OnGameStartedHandler(GameState gameState, int ammo, int lives)
{
    // Do something
}


// Event would be subscribed to like this:
Messenger.OnGameStarted += OnGameStartedHandler;

// or this:
Messenger.OnGameStarted.Subscribe(OnGameStartedHandler);

调度员

最后,我希望能够发送任何这样的事件,如下所示:

Messenger.OnGameStarted(gameState, ammoCount, livesCount);

// or

Messenger.OnGameStarted.Invoke(gameState, ammoCount, livesCount);

有没有办法轻松干净地做这样的事情? 我希望它能够非常快速地创建新事件(无需创建新类或任何样板代码)

基本上, Messenger类将充当特定事件的中心枢纽,可以从单个位置轻松引用和管理。

我建议使用标准的.NET事件机制。 您需要事件声明和raise方法驻留在静态类中,因为外部代码只允许订阅/取消订阅事件(直接)。

public static class Messenger
{
    public static event Action<GameStateMessage> GameStateChanged;
    public static void OnGameStateChanged (GameStateMessage arg) => GameStateChanged?.Invoke(arg);

    public static event Action<Message> GameStarted;
    public static void OnGameStarted (Message arg) => GameStarted?.Invoke(arg);
}

Messenger.GameStarted += (Message arg) => // Subscribing to the event
{
    Console.WriteLine(arg);
};

Messenger.OnGameStarted(new Message("Get ready!")); // Raising the event

空条件运算符?. 是必需的,因为没有订阅的事件是空引用。 它还可以处理多线程场景中的竞争条件。


更新:关于内存泄漏,每次对象订阅另一个对象的事件时,都会在两个对象之间创建连接。 基本原则是:

订阅者不保留发布者的引用。 只有发布者保留订阅者的引用。

这意味着长期存在的发布者可能会阻止短期订阅者进行垃圾回收。 订阅活动时需要注意这一点。 出版商是否应该超过我? 如果答案是肯定的,那么在我死之前我必须取消订阅。 在特定情况下,发布者是一个静态类,永远不会被垃圾收集,因此所有具有生命周期的对象都会缩短,以至于应用程序的生命周期应该取消订阅他们之前订阅的静态事件。 否则会发生内存泄漏。 以下是订阅取消订阅的示例:

public class Player : IDisposable
{
    public Player() // Constructor
    {
        Messenger.GameStarted += Messenger_GameStarted; // Subscribe
    }

    private void Messenger_GameStarted(Message arg) // Event handler
    {
        Console.WriteLine(arg);
    }

    public void Dispose() // This method must be called when the object is about to perish
    {
        Messenger.GameStarted -= Messenger_GameStarted; // Unsubscribe
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM