Code-first for gRPC

View on GitHub

ServiceModel.Grpc client configuration


ClientFactory does not have any static methods as usually default configuration is good only for “hello world” project.

public static class Program
    private static readonly IClientFactory DefaultClientFactory
        = new ClientFactory(new ServiceModelGrpcClientOptions
            MarshallerFactory = ...
            DefaultCallOptionsFactory = () => ...
            ErrorHandler = ...

    public static async Task Main(string[] args) { }



The method generates a proxy for IMyContract via Reflection.Emit and applies the configuration for proxy.

DefaultClientFactory.AddClient<IMyContract>(options =>
    // setup ServiceModelGrpcClientOptions for this client
    // by default options contain values from default factory configuration

IClientFactory.AddClient<TContract>(IClientBuilder<TContract>, Action<ServiceModelGrpcClientOptions>?)

The method registers a specific proxy builder for IMyContract and applies the configuration for proxy. The method is used by source code generator.

Configure ServiceModel.Grpc.DesignTime to generate a source code of IMyContract proxy:

internal static partial class MyGrpcServices
    // generated code ...
    public static IClientFactory AddMyContractClient(this IClientFactory clientFactory, Action<ServiceModelGrpcClientOptions> configure = null) {}

register generated proxy IMyContract:

DefaultClientFactory.AddMyContractClient(options =>
    // setup ServiceModelGrpcClientOptions for this client
    // by default options contain values from default factory configuration


CreateClient creates an new instance of a specific client with previously assigned configuration.

Silent proxy generation (Reflection.Emit)

In this example

public interface IContract
    Task<T> SumAsync<T>(T x, T y);

    void Dispose();

var client = DefaultClientFactory.CreateClient<IContract>()

the proxy will be created by the factory without any errors, but at runtime a method invocation will throw NotSupportedException:

// throw NotSupportedException("... generic methods are not supported ...")
client.SumAsync<int>(1, 3);

// throw NotSupportedException("... method is not operation contract ...")

Use ServiceModelGrpcClientOptions.Logger to see warnings from ClientFactory.

One contract, but 2 clients with different configuration

public interface IContract { }

var factory1 = new ClientFactory(/* configuration 1*/);
var factory2 = new ClientFactory(/* configuration 2*/);

// client with configuration 1
var client1 = factory1.CreateClient<IContract>();
// client with configuration 2
var client2 = factory2.CreateClient<IContract>();

Make your ClientFactory instance singleton

var factory = new ClientFactory();
for (var i=0; i<10; i++)