简体   繁体   English

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

[英]C# Generics and using the non-generic version from typed method

I'm using the RestSharp library to access a REST API. 我正在使用RestSharp库来访问REST API。

I want all the API requests to go through the same method, so I can add headers, handle errors and do other stuff in a central place. 我希望所有API请求都通过相同的方法,因此我可以添加标头,处理错误并在中心位置执行其他操作。

So I made a method that accepts a generic Func<> and that solves most of my problems, but I don't know how to handle the case where I don't have a return type. 所以我创建了一个接受泛型Func<>的方法,它解决了我的大部分问题,但我不知道如何处理我没有返回类型的情况。

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

    return response.Data;
}

I call it like this: 我称之为:

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

But I came across a problem, a bunch of API calls don't have a return type because they don't return data. 但是我遇到了一个问题,一堆API调用没有返回类型,因为它们不返回数据。 So I used Client.Execute(req) and I get the error saying the type arguments cannot be inferred, I tried to pass , but that failed because it couldn't convert the non-generic IRestResponse to the typed one. 所以我使用Client.Execute(req)并且我得到错误,说明无法推断类型参数,我试图通过,但是失败了因为它无法将非泛型IRestResponse转换为键入的类型。

Any ideas on how to tackle this in a nice way? 关于如何以一种好的方式解决这个问题的任何想法?

One thing you could try is to add an overload to your PerformApiCall function that takes a Func with a non-generic result type, and returns nothing: 您可以尝试的一件事是向PerformApiCall函数添加一个重载,该函数采用具有非泛型结果类型的Func ,并且不返回任何内容:

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

Then, depending on how complex your error checking/logic is, you could move it out to a separate method (which returns the response), and call it from both overloads of PerformApiCall : 然后,根据您的错误检查/逻辑的复杂程度,您可以将其移出到单独的方法(返回响应),并从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;

You were getting a compiler error because it is sound to treat a subtype as if it was an instance of its supertype , but it is not sound to do it in the other direction (which is what was happening when you changed your calling code to just Client.Execute(req) , returning a non-generic). 您收到编译器错误,因为将子类型视为其超类型的实例是合理的,但是在另一个方向上执行此操作并不合适 (这是将您的调用代码更改为刚刚发生的情况) Client.Execute(req) ,返回非泛型)。

Here's an ideone paste illustrating this: http://ideone.com/T2mQfl 这是一个ideone粘贴,说明了这一点: http ://ideone.com/T2mQfl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM