Table of Contents

Class JsonRpc

Namespace
Nerdbank.JsonRpc
Assembly
Nerdbank.JsonRpc.dll
[TypeShape(Kind = TypeShapeKind.None)]
public class JsonRpc : IDisposableObservable, IDisposable, IJsonRpcClient
Inheritance
JsonRpc
Implements
Inherited Members

Constructors

JsonRpc(JsonRpcPipeChannel)

Initializes a new instance of the JsonRpc class over a pipe channel.

public JsonRpc(JsonRpcPipeChannel channel)

Parameters

channel JsonRpcPipeChannel

The channel used to exchange messages.

JsonRpc(JsonRpcPipeChannel, JsonRpcOptions?)

Initializes a new instance of the JsonRpc class over a pipe channel.

public JsonRpc(JsonRpcPipeChannel channel, JsonRpcOptions? options)

Parameters

channel JsonRpcPipeChannel

The channel used to exchange messages.

options JsonRpcOptions

The immutable configuration, which may be shared by other connections, or null to use the default options.

Properties

ActivitySource

Gets the activity source used to create JSON-RPC client and server activities.

public static ActivitySource ActivitySource { get; }

Property Value

ActivitySource

Remarks

Subscribe to this source with ActivityListener or an OpenTelemetry tracer provider.

Completion

Gets a task that completes when the connection has shut down.

public Task Completion { get; }

Property Value

Task

Remarks

Deliberate disposal and EOF between messages without pending outbound requests succeed. Other connection failures fault this task with the original cause. EOF with pending requests faults it with EndOfStreamException.

IsDisposed

Gets a value indicating whether deliberate or automatic shutdown has begun.

public bool IsDisposed { get; }

Property Value

bool

JoinableTaskFactory

Gets or initializes the JoinableTaskFactory to participate in to mitigate deadlocks with the main thread.

public JoinableTaskFactory? JoinableTaskFactory { get; init; }

Property Value

JoinableTaskFactory

Defaults to null.

Remarks

When set, outbound requests carry a token that identifies the caller's JoinableTask (if any), and inbound requests that carry such a token are dispatched within a JoinableTask that is joined to it. This allows a remote party to call back into this process and reach the main thread while the original caller blocks it waiting on the outbound request.

The token is exchanged as the top-level joinableTaskToken JSON-RPC envelope property, compatible with StreamJsonRpc. Initialize this property before calling Start().

JoinableTaskTracker

Gets or initializes the JoinableTaskTokenTracker used to forward JoinableTask tokens from inbound requests to outbound requests when JoinableTaskFactory is null.

public JoinableTaskTokenTracker JoinableTaskTracker { get; init; }

Property Value

JoinableTaskTokenTracker

Defaults to an instance shared with all other JsonRpc instances that do not set this property.

Remarks

This property is ignored when JoinableTaskFactory is set.

Set this only in advanced scenarios where one process has many JsonRpc instances connected to different remote parties and correlating tokens across them is undesirable. Initialize this property before calling Start().

Logger

Gets or initializes the logger for request, connection, and transport diagnostics.

public ILogger Logger { get; init; }

Property Value

ILogger

Defaults to Instance.

Remarks

Setting this property also configures the underlying channel to use the same logger.

MarshaledProxyOptions

Gets or initializes the options used for proxies implicitly created for RPC-marshalable objects.

public JsonRpcProxyOptions MarshaledProxyOptions { get; init; }

Property Value

JsonRpcProxyOptions

Defaults to Default, the same naming convention used for ordinary RPC proxies.

Remarks

To communicate with StreamJsonRpc's default RPC-marshalable objects, set this property to new() { MethodNameTransform = CommonMethodNameTransforms.Identity } in the JsonRpc object initializer. This does not change options for proxies attached through Attach<T>(JsonRpcProxyOptions?).

Exceptions

ArgumentNullException

Thrown when set to null.

MarshaledTargetOptions

Gets or initializes the options used when implicitly registering RPC-marshalable targets.

public JsonRpcTargetOptions MarshaledTargetOptions { get; init; }

Property Value

JsonRpcTargetOptions

Defaults to Default, the same naming convention used for ordinary RPC targets.

Remarks

To communicate with StreamJsonRpc's default RPC-marshalable objects, set this property to new() { MethodNameTransform = CommonMethodNameTransforms.Identity } in the JsonRpc object initializer. This does not change options for targets registered through AddRpcTarget<T>(T, ITypeShape<T>, JsonRpcTargetOptions?).

Exceptions

ArgumentNullException

Thrown when set to null.

MaximumMessageSize

Gets or initializes the maximum encoded message size, in bytes.

public int MaximumMessageSize { get; init; }

Property Value

int

Defaults to 8 MiB. The built-in JSON and MessagePack channels apply this limit to received messages; the JSON channel also applies it to sent messages.

Exceptions

ArgumentOutOfRangeException

Thrown when set to zero or a negative value.

MultiplexingStream

Gets or initializes the multiplexing stream used to send and receive out-of-band streams.

public MultiplexingStream? MultiplexingStream { get; init; }

Property Value

MultiplexingStream

Remarks

Initialize this property before calling Start().

Options

Gets the immutable options used to configure this connection.

public JsonRpcOptions Options { get; }

Property Value

JsonRpcOptions

State

Gets the connection's lifecycle state, retaining the original shutdown mode after disposal.

public JsonRpcState State { get; }

Property Value

JsonRpcState

SynchronizationContext

Gets or initializes the SynchronizationContext that schedules the start of each inbound RPC method invocation.

public SynchronizationContext? SynchronizationContext { get; init; }

Property Value

SynchronizationContext

Defaults to a private NonConcurrentSynchronizationContext instance (configured as non-sticky) that guarantees inbound method invocations begin in the order the remote party sent the requests.

Remarks

With the default value, inbound requests are dispatched on the thread pool, one at a time, in the order they arrive. Because the default context is non-sticky, it does not become Current while a method runs. As soon as a method yields at its first await (or returns), the next queued method may begin. Long-running methods therefore execute and complete concurrently with each other and in any order; only the order in which they start is guaranteed to match the order the client sent them.

Set this property to null to remove the ordering guarantee entirely. Each inbound invocation is then queued to the thread pool independently, so invocations may begin in any order and with full concurrency. This offers the highest throughput and is appropriate when the order in which methods start does not matter.

Alternatively, initialize this property with your own SynchronizationContext (for example, one that marshals to an application's main thread) to have every inbound method invocation begin execution on that context. A context that runs callbacks one at a time preserves the ordering guarantee described above; one that runs them concurrently does not. As with the default, a method's continuations after its first await are subject to normal await semantics and only return to this context if the context applies itself as Current and the method does not use ConfigureAwait(bool) with false.

Work that precedes the invocation (such as request parsing and cancellation bookkeeping) always runs on the reader loop in message order and is unaffected by this property.

Inbound $/cancelRequest notifications are exempt from this property and always begin on the thread pool. Because their purpose is to interrupt work that is already running, queueing them behind that work would prevent a handler that occupies the dispatcher without yielding from ever being canceled.

TerminationException

Gets the original connection-loss cause, or null if no connection loss occurred.

public Exception? TerminationException { get; }

Property Value

Exception

Remarks

Retained after a user calls Dispose(), including EOF for which Completion succeeded.

Methods

AddRpcTarget<T>(T, JsonRpcTargetOptions?)

Registers a local object's public instance methods as JSON-RPC targets, invoked when incoming requests match their JSON-RPC method names.

public void AddRpcTarget<T>(T target, JsonRpcTargetOptions? options = null) where T : IShapeable<T>

Parameters

target T

The object whose methods should be invoked in response to matching incoming requests and notifications.

options JsonRpcTargetOptions

Options controlling method name resolution for this target. When null, default options are used.

Type Parameters

T

The statically shaped type describing which members of target to register.

Remarks

Register all initial targets before calling Start() so the listener is ready to dispatch every method as soon as it begins reading messages.

AddRpcTarget<T>(T, ITypeShape<T>, JsonRpcTargetOptions?)

Registers a local object's public instance methods as JSON-RPC targets, invoked when incoming requests match their JSON-RPC method names.

public void AddRpcTarget<T>(T target, ITypeShape<T> shape, JsonRpcTargetOptions? options = null)

Parameters

target T

The object whose methods should be invoked in response to matching incoming requests and notifications.

shape ITypeShape<T>

The type shape describing target's methods.

options JsonRpcTargetOptions

Options controlling method name resolution for this target. When null, default options are used.

Type Parameters

T

The type describing which members of target to register.

Remarks

Register all initial targets before calling Start() so the listener is ready to dispatch every method as soon as it begins reading messages.

Attach(Type, JsonRpcProxyOptions?)

Attaches a generated client proxy for an RPC contract interface to this JSON-RPC connection.

public object Attach(Type interfaceType, JsonRpcProxyOptions? options = null)

Parameters

interfaceType Type

The RPC contract interface to proxy.

options JsonRpcProxyOptions

Options controlling argument encoding for this proxy.

Returns

object

A generated proxy instance that implements interfaceType.

Remarks

The generated proxy factory is looked up once per interface and cached. When the interface is known at compile time, Attach<T>(JsonRpcProxyOptions?) is slightly faster because it avoids the dictionary lookup.

Attach<T>(JsonRpcProxyOptions?)

Attaches a generated client proxy for an RPC contract interface to this JSON-RPC connection.

public T Attach<T>(JsonRpcProxyOptions? options = null)

Parameters

options JsonRpcProxyOptions

Options controlling argument encoding for this proxy.

Returns

T

A generated proxy instance that implements T.

Type Parameters

T

The RPC contract interface to proxy.

CreateArguments(bool, int, CancellationToken)

Creates a serializer-neutral builder for named or positional arguments.

public JsonRpcArgumentsBuilder CreateArguments(bool named, int count, CancellationToken cancellationToken = default)

Parameters

named bool

Whether to use named arguments.

count int

The exact number of arguments to write.

cancellationToken CancellationToken

A token used when serializing all arguments.

Returns

JsonRpcArgumentsBuilder

An argument builder using this client's serializer.

CreateBatch()

Creates a one-shot builder for sending multiple JSON-RPC requests and notifications as one protocol payload.

public JsonRpcBatch CreateBatch()

Returns

JsonRpcBatch

A batch builder associated with this JSON-RPC connection.

Dispose()

Deliberately disposes this connection and rejects subsequent calls with ObjectDisposedException.

public void Dispose()

Remarks

Preserves any prior connection-loss cause in TerminationException and does not overwrite the original State or Completion outcome. Await Completion to observe asynchronous teardown.

NotifyAsync(string, JsonRpcValue, CancellationToken)

Sends a notification with arguments already serialized using the channel's selected encoding.

public ValueTask NotifyAsync(string method, JsonRpcValue arguments, CancellationToken cancellationToken)

Parameters

method string

The name of the remote method to invoke.

arguments JsonRpcValue

The pre-serialized arguments payload.

cancellationToken CancellationToken

A token whose cancellation is observed before the notification is posted.

Returns

ValueTask

A task that completes when the notification has been accepted by the outbound channel.

Remarks

Consume the returned awaitable once. To share it, await it repeatedly, or compose it with other Tasks, call AsTask() or Preserve() once and retain the returned awaitable instead of the original. It may be backed by a pooled source that is recycled after consumption.

NotifyAsync<TArg>(string, in TArg, ITypeShape<TArg>, CancellationToken)

public ValueTask NotifyAsync<TArg>(string method, in TArg arguments, ITypeShape<TArg> argShape, CancellationToken cancellationToken)

Parameters

method string
arguments TArg
argShape ITypeShape<TArg>
cancellationToken CancellationToken

Returns

ValueTask

Type Parameters

TArg

NotifyAsync<TArg>(string, in TArg, CancellationToken)

public ValueTask NotifyAsync<TArg>(string method, in TArg arguments, CancellationToken cancellationToken) where TArg : IShapeable<TArg>

Parameters

method string
arguments TArg
cancellationToken CancellationToken

Returns

ValueTask

Type Parameters

TArg

RequestAsync(string, JsonRpcValue, CancellationToken)

Sends a request with arguments already serialized using the channel's selected encoding.

public ValueTask RequestAsync(string method, JsonRpcValue arguments, CancellationToken cancellationToken)

Parameters

method string

The name of the remote method to invoke.

arguments JsonRpcValue

The pre-serialized arguments payload.

cancellationToken CancellationToken

A token whose cancellation should be propagated to the remote endpoint.

Returns

ValueTask

A task that completes when the remote endpoint sends its response.

Remarks

Consume the returned awaitable once. To share it, await it repeatedly, or compose it with other Tasks, call AsTask() or Preserve() once and retain the returned awaitable instead of the original. It may be backed by a pooled source that is recycled after consumption. A remote RequestCancelled response throws OperationCanceledException. Cancellation exceptions include cancellationToken only if it is canceled. Unrequested remote cancellation has a message explaining that the remote party canceled processing without caller-requested cancellation. The original remote error is retained as a JsonRpcException inner exception; other remote errors throw JsonRpcException.

RequestAsync<TResult>(string, JsonRpcValue, ITypeShape<TResult>, CancellationToken)

Sends a request with arguments already serialized using the channel's selected encoding.

public ValueTask<TResult> RequestAsync<TResult>(string method, JsonRpcValue arguments, ITypeShape<TResult> resultShape, CancellationToken cancellationToken)

Parameters

method string

The name of the remote method to invoke.

arguments JsonRpcValue

The pre-serialized arguments payload.

resultShape ITypeShape<TResult>

The type shape describing TResult.

cancellationToken CancellationToken

A token whose cancellation should be propagated to the remote endpoint.

Returns

ValueTask<TResult>

A task that completes with the result returned by the remote endpoint.

Type Parameters

TResult

The expected result type.

Remarks

Consume the returned awaitable once. To share it, await it repeatedly, or compose it with other Tasks, call AsTask() or Preserve() once and retain the returned awaitable instead of the original. It may be backed by a pooled source that is recycled after consumption. A remote RequestCancelled response throws OperationCanceledException. Cancellation exceptions include cancellationToken only if it is canceled. Unrequested remote cancellation has a message explaining that the remote party canceled processing without caller-requested cancellation. The original remote error is retained as a JsonRpcException inner exception; other remote errors throw JsonRpcException.

RequestAsync<TArg>(string, in TArg, ITypeShape<TArg>, CancellationToken)

public ValueTask RequestAsync<TArg>(string method, in TArg arguments, ITypeShape<TArg> argShape, CancellationToken cancellationToken)

Parameters

method string
arguments TArg
argShape ITypeShape<TArg>
cancellationToken CancellationToken

Returns

ValueTask

Type Parameters

TArg

RequestAsync<TArg>(string, in TArg, CancellationToken)

public ValueTask RequestAsync<TArg>(string method, in TArg arguments, CancellationToken cancellationToken) where TArg : IShapeable<TArg>

Parameters

method string
arguments TArg
cancellationToken CancellationToken

Returns

ValueTask

Type Parameters

TArg

RequestAsync<TArg, TResult>(string, in TArg, ITypeShape<TArg>, ITypeShape<TResult>, CancellationToken)

public ValueTask<TResult> RequestAsync<TArg, TResult>(string method, in TArg arguments, ITypeShape<TArg> argShape, ITypeShape<TResult> resultShape, CancellationToken cancellationToken)

Parameters

method string
arguments TArg
argShape ITypeShape<TArg>
resultShape ITypeShape<TResult>
cancellationToken CancellationToken

Returns

ValueTask<TResult>

Type Parameters

TArg
TResult

RequestAsync<TArg, TResult>(string, in TArg, CancellationToken)

public ValueTask<TResult> RequestAsync<TArg, TResult>(string method, in TArg arguments, CancellationToken cancellationToken) where TArg : IShapeable<TArg> where TResult : IShapeable<TResult>

Parameters

method string
arguments TArg
cancellationToken CancellationToken

Returns

ValueTask<TResult>

Type Parameters

TArg
TResult

RequestAsync<TArg, TResult, TResultProvider>(string, in TArg, CancellationToken)

public ValueTask<TResult> RequestAsync<TArg, TResult, TResultProvider>(string method, in TArg arguments, CancellationToken cancellationToken) where TArg : IShapeable<TArg> where TResultProvider : IShapeable<TResult>

Parameters

method string
arguments TArg
cancellationToken CancellationToken

Returns

ValueTask<TResult>

Type Parameters

TArg
TResult
TResultProvider

RevokeMarshaledObject(object)

Revokes every active marshaled relationship for an object owned by this connection.

public int RevokeMarshaledObject(object target)

Parameters

target object

The previously marshaled target object.

Returns

int

The number of handles revoked.

Remarks

This operation is object-wide: every handle issued for target is revoked, while handles for other objects are unaffected. Revocation does not dispose target; its owner remains responsible for its lifetime. Calls already dispatched remotely may complete.

Start()

Starts listening for and dispatching incoming messages.

public void Start()

Remarks

Call this after registering initial targets with AddRpcTarget<T>(T, ITypeShape<T>, JsonRpcTargetOptions?) to avoid rejecting incoming requests or dropping notifications for which no RPC target has yet been registered.