Search code examples
c#grpc.net-6.0grpc-dotnetgrpc-code-first

How to use polymorphism on return type of grpc code first service?


I want to use polymorphic return type in grpc service with code first approach, but I do not know how to do it?

I have service contract like below

    [ServiceContract]
    public interface IGreeterService
    {
        [OperationContract]
        BaseResponse SayHello(HelloRequest request,
            CallContext context = default);
    }

And I have two derived response like below

public class ResponseA : BaseResponse
{
string foo;
}

public class ResponseB: BaseResponse
{
string bar;
}

my BaseResponse exist in another library, and I do not want (and I can not) to change this library.

public abstract class BaseResponse
{
public string hoo;
}

So finally I want to implement SayHello like below

public class GreeterService : IGreeterService
{

  public BaseResponse SayHello(HelloRequest request, CallContext context = default)
  {
    if (request.Name == "Heelo")
    {
      return new ResponseA() {foo = "Hi", hoo = "Hey"};
    }
    else
      return new ResponseB() {bar = "bye", hoo = "You"};
  }
}

But I do not know how can I say to OperationContract that I have two type for return type?


Solution

  • If you can't alter BaseResponse, you will have to configure it manually - for example:

    RuntimeTypeModel.Default.Add(typeof(BaseResponse), false)
        // fields of BaseResponse
        .Add(1, nameof(BaseResponse.hoo))
        // sub-types of BaseResponse
        .AddSubType(10, typeof(ResponseA))
        .AddSubType(11, typeof(ResponseB));
    

    Here I'm assuming that ResponseA and ResponseB can at least be altered, i.e.

    [ProtoContract]
    public class ResponseA : BaseResponse
    {
        [ProtoMember(1)]
        public string foo;
    }
    

    If that isn't possible, you'll also need to configure them manually, for example:

    RuntimeTypeModel.Default.Add(typeof(ResponseA), false)
        .Add(1, nameof(ResponseA.foo));