C#泛型并使用类型化方法的非泛型版本

Mad*_*d0g 5 c# generics restsharp

我正在使用RestSharp库来访问REST API.

我希望所有API请求都通过相同的方法,因此我可以添加标头,处理错误并在中心位置执行其他操作.

所以我创建了一个接受泛型的方法,Func<>它解决了我的大多数问题,但我不知道如何处理我没有返回类型的情况.

private T PerformApiCall<T>(RestRequest restRequest, Func<RestRequest, IRestResponse<T>> restMethod)
{
    var response = restMethod.Invoke(restRequest);
    //handle errors
    ....

    return response.Data;
}
Run Code Online (Sandbox Code Playgroud)

我称之为:

var apples = PerformApiCall(new RestRequest('/api/apples'), req => Client.Execute<List<Apple>>(req));
Run Code Online (Sandbox Code Playgroud)

但是我遇到了一个问题,一堆API调用没有返回类型,因为它们不返回数据.所以我使用了Client.Execute(req),我得到的错误是无法推断类型参数,我试图通过,但是失败了,因为它无法将非泛型IRestResponse转换为类型的.

关于如何以一种好的方式解决这个问题的任何想法?

voi*_*hos 2

PerformApiCall您可以尝试的一件事是向您的函数添加一个重载,该重载Func采用非泛型结果类型,并且不返回任何内容:

// Notice the `Func` has `IRestResponse`, not `IRestResponse<T>`
public void PerformApiCall(RestRequest restRequest,
                           Func<RestRequest, IRestResponse> restMethod)
    ...
Run Code Online (Sandbox Code Playgroud)

然后,根据错误检查/逻辑的复杂程度,您可以将其移至单独的方法(返回响应),并从以下两个重载中调用它PerformApiCall

private T PerformRequestWithChecks<T>(RestRequest restRequest,
                                      Func<RestRequest, T> restMethod)
    where T : IRestResponse
{
    var response = restMethod.Invoke(restRequest);
    // Handle errors...
    return response;
}

// You can use it from both versions of `PerformApiCall` like so:
//
//     // From non-generic version
//     var response =
//         PerformRequestWithChecks<IRestResponse>(restRequest, restMethod);
//
//     // From generic version
//     var response =
//         PerformRequestWithChecks<IRestResponse<T>>(restRequest, restMethod);
//     return response.Data;
Run Code Online (Sandbox Code Playgroud)

您收到编译器错误,因为将子类型视为其父类型的实例是合理的,但从另一个方向执行它是不合理的(这就是当您将调用代码更改为只是时发生的情况)Client.Execute(req),返回一个非泛型)。

这是一个 ideone 粘贴,说明了这一点: http: //ideone.com/T2mQfl