Search code examples
c#unity-game-enginemonorpc

C# Dynamic Signature for RPC


In short, I want to implement a JSONRPC2 api for Unity3d (mono) to a NodeJS server.

I'm pretty new to C# and I feel that what I'm looking to do is hardly possible.

Currently I can do something like this:

JSONRequest request = new JSONRequest();
JSONNode jsonParams = new JSONNode();
....
request.params = jsonParams;
socket.Send(request.toJSON());

As you can see, making a call to a RPC is quite verbose and typing all of this takes some time.

What I'd like to have is something like this:

req = rpc.call('add', 1, 2);
req.success += SuccessCallback
req.error += ErrorCallback

Since C# doesn't allow dynamic signature, I'd have to define a signature for each possible type like

Request call(string method, int a, int b) Request call(string method, string a, int b) ...

So today I came with this idea which would make things simpler to write and pretty close to what I'd like, instead of passing parameters, I'd pass a callback method that build parameters. Then the result would get serialized.

rpc.call("add", () => [1, 2])

But I guess it doesn't help much because the delegate still has to have a particular return type which brings me nowhere.

How can I do that?


Solution

  • Params keyword

    It sounds like what you're looking for is the C# params keyword, which lets you have any number of parameters for a function. As the type of your parameters also vary, it can also just use object as a catch all. So, like this:

    public void call (string method, params object[] args) { // Any number of any type
        
        // Create the request:
        JSONRequest request = new JSONRequest();
        JSONNode jsonParams = new JSONNode();
    
        // For each arg:
        foreach (object argument in args) {
            
            // (guessing JSONNode here - I don't know if it has 'Add')
            jsonParams.Add(argument);
            
        }
    
        request.params = jsonParams;
        
    }
    

    Giving you the original intended usage:

    rpc.call("hello", "first", 2, "third");