Projects

CodeWF.EventBus

In-process event bus, supporting Command, Query and multiple IOC scenarios

项目说明

CodeWF.EventBus

CodeWF.EventBus

CodeWF.EventBus 是一个轻量的进程内事件总线库,适合在 WPF、WinForms、Avalonia UI、ASP.NET Core 和控制台程序中做模块解耦。它支持 Command 命令分发,也支持 Query<T> 查询回传,便于实现简单 CQRS。

Suitable for the scene

  • Desktop application modules do not want to directly reference each other's services or ViewModels.
  • ASP.NET Core wants to split the controller, service processor, and query logic with a lightweight event bus.
  • The Console, WinForms, WPF, or Avalonia projects do not have a unified IOC container, but still want to use subscription publishing to decouple the process.
  • 希望比 MediatR 更小、更少框架约束,同时保留 Command/Query 思路。

package selection

package applicable scenarios
CodeWF.EventBus No IOC containers or manual subscriptions.
CodeWF.AspNetCore.EventBus ASP.NET Core / MS.DI。
CodeWF.DryIoc.EventBus DryIoc / Prism。
CodeWF.IOC.EventBus Other IOC containers access registration and resolution capabilities through callbacks.

core type

public abstract class Command
{
}

public abstract class Query<TResponse> : Command
{
    public abstract TResponse Result { get; set; }
}

Example:

public sealed class CreateProductCommand : Command
{
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
}

public sealed class ProductQuery : Query<ProductItemDto?>
{
    public Guid ProductId { get; set; }
    public override ProductItemDto? Result { get; set; }
}

processor writing

事件处理方法使用 [EventHandler] 标记,参数只能有一个,且必须继承自 Command。返回值支持 voidTask,方法可以是 publicprivatestatic

[Event]
public sealed class ProductEventHandler
{
    [EventHandler]
    private async Task HandleCreateAsync(CreateProductCommand command)
    {
        await Task.CompletedTask;
    }

    [EventHandler(Order = 1)]
    private void HandleQuery(ProductQuery query)
    {
        query.Result = new ProductItemDto
        {
            Id = query.ProductId,
            Name = "Demo",
            Price = 99
        };
    }
}

No IOC containers

public sealed class MainViewModel
{
    private readonly IEventBus _eventBus = EventBus.Default;

    public MainViewModel()
    {
        _eventBus.Subscribe(this);
    }

    [EventHandler]
    private void Handle(UpdateTimeCommand command)
    {
        Console.WriteLine(command.Time);
    }
}

Issue orders and inquiries:

await EventBus.Default.PublishAsync(new CreateProductCommand
{
    Name = "XiaoMi",
    Price = 8999
});

var product = await EventBus.Default.QueryAsync(new ProductQuery
{
    ProductId = Guid.NewGuid()
});

When an instance object is no longer in use, it is recommended to proactively unsubscribe:

EventBus.Default.Unsubscribe(this);

ASP.NET Core

using CodeWF.AspNetCore.EventBus;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddEventBus();

var app = builder.Build();

app.MapControllers();
app.UseEventBus();

app.Run();

AddEventBus() 会扫描程序集中的 [Event] 类并注册到容器中,UseEventBus() 会把扫描得到的处理器接入事件总线。

warehouse