You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SignalR客户端服务注入后,如何在指定类中接收Hub消息?

在指定类中监听SignalR Hub消息的解决方案

看起来你已经搞定了SignalR客户端的服务封装和消息发送,现在就差让指定类接收Hub推送的消息了对吧?这里有几个实用的方案,你可以根据自己的项目场景选择:

方案一:通过事件订阅模式转发消息

修改你的HubClient类,把收到的Broadcast消息通过.NET事件暴露出去,让其他类可以订阅这个事件:

public class HubClient : IHub
{
    private HubConnection hubConnection;
    // 定义事件,用于转发Broadcast消息
    public event Action<string> OnBroadcastReceived;

    private async Task ConnectAsync()
    {
        // 连接操作
        hubConnection.On<string>("Broadcast", message => 
        {
            // 触发事件,把消息传递给所有订阅者
            OnBroadcastReceived?.Invoke(message);
            // 保留原来的OnBroadcast逻辑(如果需要)
            OnBroadcast(message);
        });
    }

    private void OnBroadcast(string message)
    {
        // 原来的消息处理逻辑
    }

    public async Task Send(string message)
    {
        await hubConnection.SendAsync("SendMessage", message);
    }
}

然后在你需要监听消息的指定类中,注入HubClient并订阅事件:

public class MyListenerClass
{
    private readonly HubClient _hubClient;

    public MyListenerClass(HubClient hubClient)
    {
        _hubClient = hubClient;
        // 订阅Broadcast消息事件
        _hubClient.OnBroadcastReceived += HandleBroadcastMessage;
    }

    private void HandleBroadcastMessage(string message)
    {
        // 这里写你的自定义消息处理逻辑
        Console.WriteLine($"收到广播消息:{message}");
    }

    // 如果是可释放的服务,记得取消订阅避免内存泄漏
    public void Dispose()
    {
        _hubClient.OnBroadcastReceived -= HandleBroadcastMessage;
    }
}

方案二:让指定类直接注册Hub回调

如果需要更灵活的方式,可以让HubClient提供一个方法,允许外部类直接向HubConnection注册自己的回调函数:

public class HubClient : IHub
{
    private HubConnection hubConnection;

    private async Task ConnectAsync()
    {
        // 连接操作,保留原来的OnBroadcast注册(如果需要)
        hubConnection.On<string>("Broadcast", OnBroadcast);
    }

    // 提供方法让外部类注册自定义回调
    public void RegisterBroadcastCallback(Action<string> callback)
    {
        hubConnection.On<string>("Broadcast", callback);
    }

    private void OnBroadcast(string message)
    {
        // 原来的处理逻辑
    }

    public async Task Send(string message)
    {
        await hubConnection.SendAsync("SendMessage", message);
    }
}

然后在指定类中注入HubClient并注册自己的回调:

public class MyListenerClass
{
    public MyListenerClass(HubClient hubClient)
    {
        // 注册自己的消息处理回调
        hubClient.RegisterBroadcastCallback(HandleBroadcastMessage);
    }

    private void HandleBroadcastMessage(string message)
    {
        // 自定义消息处理逻辑
        Console.WriteLine($"收到消息:{message}");
    }
}

这种方式的好处是每个监听类可以拥有完全独立的处理逻辑,不需要依赖HubClient的事件体系。

方案三:使用中介者模式统一转发(适合复杂场景)

如果你的项目中有多个类需要监听不同的SignalR消息,推荐用中介者模式(比如MediatR)来彻底解耦消息接收和处理:

  1. 首先定义一个消息接收的事件类:
public class BroadcastMessageReceived
{
    public string Message { get; set; }
}
  1. 修改HubClient,收到消息后发布这个中介者事件:
public class HubClient : IHub
{
    private HubConnection hubConnection;
    private readonly IMediator _mediator;

    public HubClient(IMediator mediator)
    {
        _mediator = mediator;
    }

    private async Task ConnectAsync()
    {
        // 连接操作
        hubConnection.On<string>("Broadcast", async message => 
        {
            OnBroadcast(message);
            // 发布中介者事件,通知所有处理器
            await _mediator.Publish(new BroadcastMessageReceived { Message = message });
        });
    }

    private void OnBroadcast(string message)
    {
        // 原来的处理逻辑
    }

    public async Task Send(string message)
    {
        await hubConnection.SendAsync("SendMessage", message);
    }
}
  1. 在指定类中实现事件处理器:
public class BroadcastMessageHandler : INotificationHandler<BroadcastMessageReceived>
{
    public Task Handle(BroadcastMessageReceived notification, CancellationToken cancellationToken)
    {
        // 自定义消息处理逻辑
        Console.WriteLine($"收到广播消息:{notification.Message}");
        return Task.CompletedTask;
    }
}

这种方式让HubClient只负责和SignalR Hub通信,消息处理逻辑完全交给各个处理器类,非常适合大型项目的解耦需求。


内容的提问来源于stack exchange,提问作者user4625198

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:22:30