microsoft / vs-streamjsonrpc

The StreamJsonRpc library offers JSON-RPC 2.0 over any .NET Stream, WebSocket, or Pipe. With bonus support for request cancellation, client proxy generation, and more.
Other
756 stars 151 forks source link

Dynamic codegen of individual delegates to invoke RPC from client #673

Open snikeguo opened 3 years ago

snikeguo commented 3 years ago

Contract:

public delegate Task DataChange(int v);

server:

do some thing.......
var dataChange=ServerJsonRpc.Attach<DataChange>( ClientInfo); //clientinfo is: client's stream /client's session(like ip and port) and so on
dataChange(newValue);
.......

client:

ClientJsonRpc.AddDelegate<DataChange>((v)=>{Console.WriteLine(...............)});

expect:When the server calls the DataChange delegate, the client will execute: Console.WriteLine(..........);

snikeguo commented 3 years ago

image

snikeguo commented 3 years ago

image

AArnott commented 3 years ago

I suppose we could technically add a method to JsonRpc that would generate code for a delegate of a given signature that would invoke some method. Your samples don't include the generation of this delegate taking the name of the server method though -- only the signature is given. Where does the method name come from?

That said, we already have robust support for convenient client proxies via our code generator that implements whole interfaces. Can you use that instead of doing it on a per-delegate basis?

snikeguo commented 3 years ago

@AArnott My English is not very good. and I don't quite understand what you mean This is an example: https://github.com/beetlex-io/BeetleX-Samples/tree/master/XRPC.DelegateInvoke

Server: https://github.com/beetlex-io/BeetleX-Samples/blob/69e9e0f15ea4d8bb4f8a740540d348866e415372/XRPC.DelegateInvoke/Server/Program.cs#L55

Client: https://github.com/beetlex-io/BeetleX-Samples/blob/69e9e0f15ea4d8bb4f8a740540d348866e415372/XRPC.DelegateInvoke/Client/DelegateApi.cs#L10

AArnott commented 3 years ago

In StreamJsonRpc this would look like:

interface IMyRpcInterface
{
    Task<List<Order>> ListOrders(int employee, string employeeid);
    Task<List<Employee> ListEmployees();
    Task<List<Customer> ListCustomers();
}

On the server you could implement that interface. On the client, you would then use:

IMyRpcInterface proxy = JsonRpc.Attach<IMyRpcInterface>(stream);
List<Employee> await proxy.ListEmployees();
snikeguo commented 3 years ago

In StreamJsonRpc this would look like:

interface IMyRpcInterface
{
    Task<List<Order>> ListOrders(int employee, string employeeid);
    Task<List<Employee> ListEmployees();
    Task<List<Customer> ListCustomers();
}

On the server you could implement that interface. On the client, you would then use:

IMyRpcInterface proxy = JsonRpc.Attach<IMyRpcInterface>(stream);
List<Employee> await proxy.ListEmployees();

@AArnott i know .it is : You are talking about the interface of Client calling Server (client call server). I want to express is: Server pushes messages to Client through "delegate event"


public delegate Task DataChange(int v);

server: do some thing....... var dataChange=ServerJsonRpc.Attach( ClientInfo); //clientinfo is: client's stream /client's session(like ip and port) and so on dataChange(newValue); .......

client:

ClientJsonRpc.AddDelegate((v)=>{Console.WriteLine(...............)});



Currently, vs-streamjsonrpc does not support "delegate event" 
AArnott commented 3 years ago

Thanks for helping me understand you're interested in reverse-direction RPC. JSON-RPC is fundamentally a p2p protocol. So there isn't really a client or a server as far as the RPC protocol is concerned. This means you can define an interface for generating a proxy for each direction. What you think as your client and server can each have a unique interface, and they can invoke each other. This provides you one option for your "server" to invoke the client given the method signature you want, and any such method can be put into a delegate in your own code.

Did you know that the RPC interface can include events?

interface IMyRpcInterface
{
    event EventHandler<ChangeDetails> EmployeesChanged;
    Task<List<Order>> ListOrders(int employee, string employeeid);
    Task<List<Employee> ListEmployees();
    Task<List<Customer> ListCustomers();
}

This can make it particularly convenient for a client/server paradigm designed interface to let the server call back to the client for notifications.

snikeguo commented 3 years ago

yes ,i find a doc: https://github.com/microsoft/vs-streamjsonrpc/blob/main/doc/dynamicproxy.md but no sample.....only document Where are examples of "delegate event"?

AArnott commented 3 years ago

I'm sorry, I don't understand your question. Every event in C# is based on delegates. On the server and client you implement and add handlers to events as if it were ordinary C# code, and StreamJsonRpc makes them just work. If you're unfamiliar with events in C#, please learn that first then come back here if it works in the local case but not over RPC.