當前位置: 妍妍網 > 碼農

CodeWF.EventBus:輕量級事件匯流排,讓通訊更流暢

2024-06-10碼農

1. CodeWF.EventBus

EventBus(事件匯流排),用於解耦模組之間的通訊。本庫( CodeWF.EventBus [1] )適用於行程內訊息傳遞(無其他外部依賴),與大家普遍使用的MediatR部份類似,但MediatR庫側重於 ASP.NET Core [2] 設計使用,而本庫也有點點優勢:

  1. 設計可在各種樣版計畫使用,如WPF、Winform、AvaloniaUI、ASP.NET Core等,主要參考了 Prism.Events [3] 設計;

  2. 參考 MASA Framework [4] 增強訊息處理能力:

internal classMessageHandler
{
[EventHandler(Order = 3)]
privatevoidReceiveAutoCreateProductMessage3(CreateProductMessage message)
{
AddLog($"收到自動訂閱訊息3({message}」");
}
[EventHandler(Order = 1)]
privatevoidReceiveAutoDeleteProductMessage(DeleteProductMessage message)
{
AddLog($"收到自動訂閱訊息({message}」");
}
[EventHandler(Order = 2)]
privatevoidReceiveAutoCreateProductMessage2(CreateProductMessage message)
{
AddLog($"收到自動訂閱訊息2({message}」");
}
}

2. 怎麽使用事件匯流排?

首先定義訊息類,訊息需要繼承自 CodeWF.EventBus.Message

public classCreateProductMessage : CodeWF.EventBus.Message
{
publicstring Name { get; }
publicCreateProductMessage(object sender, string name) : base(sender)
{
Name = name;
}
publicoverridestringToString()
{
return$"建立產品訊息-】產品名稱:{Name}";
}
}
public classDeleteProductMessage : CodeWF.EventBus.Message
{
publicstring Id { get; }
publicDeleteProductMessage(object sender, string id) : base(sender)
{
Id = id;
}
publicoverridestringToString()
{
return$"刪除產品訊息-】產品Id:{Id}";
}
}



定義好訊息,這裏我們有兩種方式使用事件匯流排,非IOC和IOC方式:

  1. 非IOC方式:需要安裝 CodeWF.EventBus 包,適用於未使用IOC的樣版程式,比如WPF、Winform、AvaloniaUI、控制台程式,當然ASP.NET Core也能用。

  2. IOC方式:需要安裝 CodeWF.AspNetCore.EventBus 包,適合於在ASP.NET Core程式中使用。

2.1. 非IOC方式使用

適合於未使用IOC方式使用事件匯流排,比如在WPF、Winform、AvaloniaUI、控制台等程式中直接使用事件幫助類的靜態例項,下面是使用步驟。

建立計畫(不限於計畫型別,比如控制台程式),透過NuGet引入 CodeWF.EventBus 包:

Install-Package CodeWF.EventBus -Version 1.0.1

建立訊息處理常式,這裏參考了Prism.Events設計,可訂閱訊息、取消訂閱訊息、釋出訊息,適合於手工指定處理方法:

internal classMessageHandler
{
internalvoidManuSubscribe()
{
Messenger.Default.Subscribe<CreateProductMessage>(this, ReceiveManuCreateProductMessage);
Messenger.Default.Subscribe<DeleteProductMessage>(this, ReceiveManuDeleteProductMessage);
}
internalvoidManuUnsubscribe()
{
Messenger.Default.Unsubscribe<CreateProductMessage>(this, ReceiveManuCreateProductMessage);
Messenger.Default.Unsubscribe<DeleteProductMessage>(this, ReceiveManuDeleteProductMessage);
}
internalvoidPublish()
{
Messenger.Default.Publish(thisnew CreateProductMessage(this$"{DateTime.Now:HHmmss}號產品"));
Messenger.Default.Publish(thisnew DeleteProductMessage(this$"{DateTime.Now:HHmmss}號"));
}
voidReceiveManuCreateProductMessage(CreateProductMessage message)
{
AddLog($"收到手動註冊的{message}");
}
voidReceiveManuDeleteProductMessage(DeleteProductMessage message)
{
AddLog($"收到手動註冊的{message}");
}
privatevoidAddLog(string message)
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss fff}{message}\r\n");
}
}



最後是訊息使用:

using ConsoleDemo.EventBus;
var handler = new MessageHandler();
Console.WriteLine("1、未註冊時釋出訊息:");
handler.Publish();
Console.WriteLine();
Console.WriteLine("2、手動註冊後釋出訊息:");
handler.ManuSubscribe();
handler.Publish();
Console.WriteLine("3、取消手動註冊後釋出訊息:");
handler.ManuUnsubscribe();
handler.Publish();
Console.ReadKey();



如果訊息較多,也可使用自動註冊訊息處理方法,我們修改處理常式:

internal classMessageHandler
{
internalvoidAutoSubscribe()
{
Messenger.Default.Subscribe(this);
}
internalvoidAutoUnsubscribe()
{
Messenger.Default.Unsubscribe(this);
}
internalvoidPublish()
{
Messenger.Default.Publish(thisnew CreateProductMessage(this$"{DateTime.Now:HHmmss}號產品"));
Messenger.Default.Publish(thisnew DeleteProductMessage(this$"{DateTime.Now:HHmmss}號"));
}
[EventHandler(Order = 3)]
privatevoidReceiveAutoCreateProductMessage3(CreateProductMessage message)
{
AddLog($"收到自動訂閱訊息3({message}」");
}
[EventHandler(Order = 1)]
privatevoidReceiveAutoDeleteProductMessage(DeleteProductMessage message)
{
AddLog($"收到自動訂閱訊息({message}」");
}
[EventHandler(Order = 2)]
privatevoidReceiveAutoCreateProductMessage2(CreateProductMessage message)
{
AddLog($"收到自動訂閱訊息2({message}」");
}
privatevoidAddLog(string message)
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss fff}{message}\r\n");
}
}




[EventHandler(Order = 0)] 定義訊息的執行順序。每個訊息都可以匹配多個處理常式。一個類中可以有多個訊息處理方法,可以訂閱同一個訊息,也可以訂閱不同的訊息。

支持訊息處理常式的登出:

  1. 登出指定處理常式: Messenger.Default.Unsubscribe<CreateProductMessage>(this, ReceiveManuCreateProductMessage)

  2. 登出指定類的所有處理常式: Messenger.Default.Unsubscribe(this)

訊息使用:

using ConsoleDemo.EventBus;
var handler = new MessageHandler();
Console.WriteLine("1、未註冊時釋出訊息:");
handler.Publish();
Console.WriteLine();
Console.WriteLine("2、自動註冊後釋出訊息:");
handler.AutoSubscribe();
handler.Publish();
Console.WriteLine("3、取消自動註冊後釋出訊息:");
handler.AutoUnsubscribe();
handler.Publish();
Console.ReadKey();



2.2. IOC方式使用

適合於在ASP.NET Core程式中使用,下面是使用步驟。

建立計畫(ASP.NET Core模組計畫,比如Web API、MVC、Razor Page、Blazor Server等),透過NuGet引入 CodeWF.AspNetCore.EventBus :

Install-Package CodeWF.AspNetCore.EventBus -Version 1.0.1

建立訊息處理常式,處理類中可以正常使用建構函式註入IOC服務:

public classMessageHandler
{
privatereadonly ITimeService timeService;
publicMessageHandler(ITimeService timeService)
{
this.timeService = timeService;
}
[EventHandler(Order = 3)]
publicvoidReceiveAutoCreateProductMessage3(CreateProductMessage message)
{
AddLog($"收到訊息3({message}」");
}
[EventHandler(Order = 1)]
publicvoidReceiveAutoDeleteProductMessage(DeleteProductMessage message)
{
AddLog($"收到訊息({message}」");
}
[EventHandler(Order = 2)]
publicvoidReceiveAutoCreateProductMessage2(CreateProductMessage message)
{
AddLog($"收到訊息2({message}」");
}
privatevoidAddLog(string message)
{
Console.WriteLine($"{timeService.GetTime()}{message}\r\n");
}
}
publicinterfaceITimeService
{
stringGetTime();
}
public classTimeService : ITimeService
{
publicstringGetTime()
{
return DateTime.Now.ToString("HH:mm:ss fff");
}
}



在Program中註冊事件匯流排:

using CodeWF.AspNetCore.EventBus;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 用於測試事件處理類正常使用IOC功能
builder.Services.AddSingleton<ITimeService, TimeService>();
// 1、註冊事件匯流排,將標註`EventHandler`特性方法的類采用單例方式註入IOC容器
builder.Services.AddEventBus();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
// 2、將上面已經註入IOC容器的類取出、關聯處理方法到事件匯流排管理
app.UseEventBus();
app.Run();







在控制器或其他服務可以釋出訊息,上面的處理常式會接收處理:

[ApiController]
[Route("[controller]")]
public classEventController : ControllerBase
{
privatereadonly ILogger<EventController> _logger;
privatereadonly IMessenger _messenger;
publicEventController(ILogger<EventController> logger, IMessenger messenger)
{
_logger = logger;
_messenger = messenger;
}
[HttpPost]
publicvoidAdd()
{
_messenger.Publish(thisnew CreateProductMessage(this$"{DateTime.Now:HHmmss}號產品"));
}
[HttpDelete]
publicvoidDelete()
{
_messenger.Publish(thisnew DeleteProductMessage(this$"{DateTime.Now:HHmmss}號"));
}
}

3. 總結

CodeWF.EventBus,一款靈活的事件匯流排庫,實作模組間解耦通訊。支持多種.NET計畫型別,如WPF、WinForms、ASP.NET Core等。采用簡潔設計,輕松實作事件的釋出與訂閱。透過有序的訊息處理,確保事件得到妥善處理。簡化您的程式碼,提升系統可維護性。立即體驗CodeWF.EventBus,讓事件處理更加高效!

倉庫地址是https://github.com/dotnet9/CodeWF.EventBus,開發過程中參考不少開源計畫,他們是:

  1. Prism.Events

  2. MediatR

  3. MASA Framework

參考資料

[1]

CodeWF.EventBus: https://www.nuget.org/packages?q=CodeWF.EventBus

[2]

ASP.NET Core: https://learn.microsoft.com/zh-cn/aspnet/core/?view=aspnetcore-9.0

[3]

Prism.Events: https://github.com/PrismLibrary/Prism/tree/master/src/Prism.Events

[4]

MASA Framework: https://docs.masastack.com/framework/tutorial/mf-part-3#p-69828ff0