Over overloaded method I am using SignalR to send notifications to clients. I use IClientProxy which is a proxy for invoking hub methods.
It has 10 overload methods for SendAsync that takes parameters one by one as you see below, however, to handle this situation I have written a spagetti style method which is really weird to me.
Could you please give some suggestion?
private async Task InvokeNotification(string userName, string methodName, params object[] parameters)
{
    if (connections.ContainsKey(userName))
    {
        var proxy = Clients.Clients(connections[userName]);
        switch (parameters.Length)
        {
            case 0:
                await proxy.SendAsync(methodName);
                break;

            case 1:
                await proxy.SendAsync(methodName, parameters[0]);
                break;

            case 2:
                await proxy.SendAsync(methodName, parameters[0], parameters[1]);
                break;

            default:
                throw new HubException($&quot;No method was defined with {parameters.Length} parameters in Hub&quot;);
        }
    }
}

The following code block is the definition of SendAsync which is coming from SignalR
public static class ClientProxyExtensions
{
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, object arg2, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, object arg1, CancellationToken cancellationToken = default);
    public static Task SendAsync(this IClientProxy clientProxy, string method, CancellationToken cancellationToken = default);
}
As for me, this code is fine. Maybe there's some Reflection dark magic available but this one will be anyway faster.
The only thing I can suggest here is optimizing out an async State Machine because there's no code after await and the only await in the method can be executed.
Also note that you lookup through the Dictionary twice, first time when you check key with .ContainsKey, second time when you get the value with the same key. It can be done with single lookup using Dictionary.TryGetValue() method.
Also I suggest to follow async naming policy suggested by Microsoft, and rename the method to InvokeNotificationAsync.
private Task InvokeNotificationAsync(string userName, string methodName, params object[] parameters)
{
    if (connections.TryGetValue(userName, out var connection))
    {
        var proxy = Clients.Clients(connection);
        switch (parameters.Length)
        {
            case 0:
                return proxy.SendAsync(methodName);
                break;

            case 1:
                return proxy.SendAsync(methodName, parameters[0]);
                break;

            case 2:
                return proxy.SendAsync(methodName, parameters[0], parameters[1]);
                break;

            default:
                throw new HubException($&quot;No method was defined with {parameters.Length} parameters in Hub&quot;);
        }
    }
}

Also it can look a bit better with C# 8.0 syntax
private Task InvokeNotificationAsync(string userName, string methodName, params object[] parameters)
{
    if (connections.TryGetValue(userName, out var connection))
    {
        var proxy = Clients.Clients(connection);
        return parameters.Length switch
        {
            0 =&gt; proxy.SendAsync(methodName),
            1 =&gt; proxy.SendAsync(methodName, parameters[0]),
            2 =&gt; proxy.SendAsync(methodName, parameters[0], parameters[1]),
            _ =&gt; throw new HubException($&quot;No method was defined with {parameters.Length} parameters in Hub&quot;)
        };
    }
}