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

124 Views Asked by At

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?

1

There are 1 best solutions below

5
Marc Gravell On BEST ANSWER

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));