2

I have to use specific API which I don't have control over:

TResponse Request<TRequest, TResponse>(TRequest request) 
    where TRequest : class 
    where TResponse : class;

This is an RPC wrapper for RabbitMq from EasyNetQ library

I would like to have some way to define TRequest to TResponse relation, so that I don't have to manually match them every call like this :

this._client.Request<CancelPaymentByMerchantRequest, CancelPaymentByMerchantResponse>(request);

The solution I come up with is :

public interface ICommand<TRequest, TResponse> { }

public class StartCommand : ICommand<StartCommand, StartResponse>
{
    public int Id { get; set; }

    public string Args { get; set; }
}

public class StartResponse
{
    public bool Success { get; set; }

    public string Error { get; set; }
}

And a consumer for it :

 public TResponse Send<TRequest, TResponse>(ICommand<TRequest, TResponse> payload)
            where TRequest : class
            where TResponse : class
        {
            var result = client.Request<TRequest, TResponse>((TRequest)payload);
            return result;
        }

Is it possible to get rid of TRequest type on ICommand marker interface?

I am also worried about extra costs related to having marker interface, and then direct cast from it in the actual library call.

Any advice would be appreciated.

v00d00
  • 3,215
  • 3
  • 32
  • 43

1 Answers1

3

The simplest way to achieve this would just be to add an abstraction around Send once per TRequest type:

public SpecificResponse Send(SpecificRequest payload)
{
    return Send<SpecificRequest, SpecificResponse>(payload);
}

You'll have to define an overload for Send per TRequest, TResponse pair but then the rest of your application can use these "strongly-typed" versions to avoid having to restate the relationship everywhere.

How you orchestrate this is up to you but I'd prefer an interface/class per request/response type that acts as an intermediary to the generic layer (alternatively one big interface with a bunch of contracts on it would work just as well).

Ant P
  • 24,820
  • 5
  • 68
  • 105