Cysharp / MagicOnion

Unified Realtime/API framework for .NET platform and Unity.
MIT License
3.8k stars 424 forks source link

Add support for interface inheritance on StreamingHub #722

Closed mayuki closed 9 months ago

mayuki commented 9 months ago

This PR enables inheritance in StreamingHub interface definitions.

This allows for the consolidation of methods when multiple StreamingHub implementations need to have the same methods.

public interface IHeartbeatable
{
    Task PingAsync();
}

public interface IHeartbeatableReceiver
{
    void Pong();
}

public interface IChatHub : IStreamingHub<IChatHub, IChatHubReceiver>, IHeartbeatable
{
    Task SendAsync(string message);
}

public interface IChatHubReceiver : IHeartbeatableReceiver
{
    void OnMessage(string name, string message);
    void OnJoin(string name);
}

public interface IPollHub : IStreamingHub<IPollHub, IPollHubReceiver>, IHeartbeatable
{
    Task<(int Id, string Name)> GetSelectionsAsync();
    Task VoteAsync(int id);
}

public interface IPollHubReceiver : IHeartbeatableReceiver
{
    void OnCountUpdated(int id, int count);
}
public abstract class MyAppStreamingHubBase<THubInterface, TReceiver> : StreamingHubBase<THubInterface, TReceiver>, IHeartbeatable
    where THubInterface : IStreamingHub<THubInterface, TReceiver>
    where TReceiver : IHeartbeatableReceiver
{
    IGroup groupHeartbeatForSelf = default!;

    protected sealed override async ValueTask OnConnecting()
    {
        groupHeartbeatForSelf = await Group.AddAsync($"Heartbeat-{Context.ContextId}");
        await OnConnectingCore();
    }

    protected virtual ValueTask OnConnectingCore() => default;

    public Task PingAsync()
    {
        BroadcastToSelf(groupHeartbeatForSelf).Pong();
        return Task.CompletedTask;
    }
}
var chatHub = await StreamingHubClient.ConnectAsync<IChatHub, IChatHubReceiver>(channel, chatReceiver);
var pollHub = await StreamingHubClient.ConnectAsync<IPollHub, IPollHubReceiver>(channel, pollReceiver);

await chatHub.PingAsync(); // IHeartbeatable.PingAsync
await pollHub.PingAsync(); // IHeartbeatable.PingAsync