C#之事件总线🔥
在现代应用程序中,事件总线(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);
}
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();
}
2
3
4
5
6
事件数据接口IEventData,定义了事件数据的基本结构,包括一个Name属性和一个GetData方法,如果需要其他信息,可自行添加。
# 发布者接口
public interface IPublisher
{
string Name { get; set; }
IEventData Data { get; set; }
}
2
3
4
5
发布者接口IPublisher,定义了发布者的基本结构,包括Name属性和Data属性,如果需要其他信息,可自行添加。
# 订阅者接口
public interface ISubscribe
{
string Name { get; set; }
void OnSubscribe(IEventData data);
}
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;
}
}
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");
}
}
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; }
}
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}");
}
}
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();
}
}
}
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
2
3
4
# 总结
上述代码实现了一个基本的事件总线系统,通过定义事件总线接口和具体实现类,实现了发布者和订阅者之间的解耦。发布者可以发布事件,而订阅者可以订阅这些事件并处理相应的数据。这种设计模式在大型系统中非常有用,能够提高系统的扩展性和可维护性。