C#之事件总线🔥

1/26/2024 CSharp

在现代应用程序中,事件总线(Event Bus)是一种常用的设计模式,用于解耦发布者(Publisher)和订阅者(Subscriber)。通过事件总线,发布者可以将消息广播给多个订阅者,而无需知道订阅者的存在。本文将详细介绍如何在 C# 中实现一个简单的事件总线系统。

以下是完整的代码实现,包括事件总线接口、事件数据接口、发布者接口、订阅者接口,以及各个接口的具体实现类。

# 事件总线接口

// 事件总线接口
public interface IEventBus
{
	delegate void MyEventHandler(IEventData data);
	event MyEventHandler OnMyEvent;

	/// <summary>
	/// 注册订阅者
	/// </summary>
	/// <param name="subscribe">订阅者</param>
	void Register(ISubscribe subscribe);

	/// <summary>
	/// 移除订阅者
	/// </summary>
	/// <param name="subscribe">订阅者</param>
	void UnRegister(ISubscribe subscribe);

	/// <summary>
	/// 发布事件
	/// </summary>
	/// <param name="publisher">发布者</param>
	void Publish(IPublisher publisher);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

事件总线接口IEventBus定义了事件处理委托MyEventHandler和事件OnMyEvent,提供了Register方法用于注册订阅者,UnRegister方法用于移除订阅者,以及 Publish 方法用于发布事件。

# 事件数据接口

// 事件数据接口
public interface IEventData
{
	string Name { get; set; }
	void GetData();
}
1
2
3
4
5
6

事件数据接口IEventData,定义了事件数据的基本结构,包括一个Name属性和一个GetData方法,如果需要其他信息,可自行添加。

# 发布者接口

public interface IPublisher
{
	string Name { get; set; }
	IEventData Data { get; set; }
}
1
2
3
4
5

发布者接口IPublisher,定义了发布者的基本结构,包括Name属性和Data属性,如果需要其他信息,可自行添加。

# 订阅者接口

public interface ISubscribe
{
	string Name { get; set; }
	void OnSubscribe(IEventData data);
}
1
2
3
4
5

订阅者接口ISubscribe定义了订阅者的基本结构,包括Name属性和OnSubscribe方法,用于处理事件数据,如果需要其他信息,可自行添加。

# 事件总线实现

// 事件总线的具体实现
public class MyEventBus : IEventBus
{
	private static readonly MyEventBus _instance = new MyEventBus();
	public static MyEventBus Instance => _instance;

	private MyEventBus() { }

	public event IEventBus.MyEventHandler OnMyEvent;

	public void Publish(IPublisher publisher)
	{
		OnMyEvent?.Invoke(publisher.Data);
	}

	public void Register(ISubscribe subscribe)
	{
		OnMyEvent += subscribe.OnSubscribe;
	}

	public void UnRegister(ISubscribe subscribe)
	{
		OnMyEvent -= subscribe.OnSubscribe;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

事件总线实现MyEventBus,采用单例模式,确保系统中只有一个事件总线实例,实现了Register、UnRegister和Publish方法,用于管理订阅者和发布事件。

# 事件数据实现

// 具体的事件数据类
public class MyEventData : IEventData
{
	public string Name { get; set; }

	public void GetData()
	{
		Console.WriteLine($"我是MyEventData");
	}
}

// 另一个具体的事件数据类
public class MyEventData2 : IEventData
{
	public string Name { get; set; }

	public void GetData()
	{
		Console.WriteLine($"我是MyEventData2");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

具体的事件数据类MyEventData和MyEventData2,实现了IEventData接口,分别代表不同类型的事件数据。

# 发布者实现

public class MyPublisher : IPublisher
{
	public string Name { get; set; }
	public IEventData Data { get; set; }
}
1
2
3
4
5

具体的发布者类MyPublisher,实现了 IPublisher 接口,负责发布包含特定事件数据的事件。

# 订阅者实现

public class MySubscribe : ISubscribe
{
	public string Name { get; set; }

	public void OnSubscribe(IEventData data)
	{
		data.GetData();
		Console.WriteLine($"我是{Name}, 输入 :{data.Name}");
	}
}
1
2
3
4
5
6
7
8
9
10

具体的订阅者类MySubscribe,实现了ISubscribe接口,负责接收和处理事件数据。

# 使用示例

下面的代码演示了如何使用定义的事件总线系统,注册订阅者,发布事件,并处理这些事件。

using System;

namespace EventBusDemo
{
    class Program
    {
        static void Main()
        {
            MySubscribe subscribe = new MySubscribe();
            subscribe.Name = "I am subscribe !";

            MyPublisher publisher = new MyPublisher();
            publisher.Name = "I am publisher !";
            publisher.Data = new MyEventData() { Name = "I am MyEventData" };

            MyPublisher publisher2 = new MyPublisher();
            publisher2.Name = "I am publisher2 !";
            publisher2.Data = new MyEventData2() { Name = "I am MyEventData2" };

            MyEventBus.Instance.Register(subscribe);
            MyEventBus.Instance.Publish(publisher);
            MyEventBus.Instance.Publish(publisher2);
            MyEventBus.Instance.UnRegister(subscribe);

            Console.ReadLine();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

运行结果:

我是MyEventData
我是I am subscribe !, 输入 :I am MyEventData
我是MyEventData2
我是I am subscribe !, 输入 :I am MyEventData2
1
2
3
4

# 总结

上述代码实现了一个基本的事件总线系统,通过定义事件总线接口和具体实现类,实现了发布者和订阅者之间的解耦。发布者可以发布事件,而订阅者可以订阅这些事件并处理相应的数据。这种设计模式在大型系统中非常有用,能够提高系统的扩展性和可维护性。