Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#泛型和使用类型化方法的非泛型版本_C#_Generics_Restsharp - Fatal编程技术网

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

C#泛型和使用类型化方法的非泛型版本,c#,generics,restsharp,C#,Generics,Restsharp,我正在使用RestSharp库访问RESTAPI 我希望所有的API请求都通过相同的方法,这样我就可以在一个中心位置添加头、处理错误和其他事情 因此,我创建了一个方法,它接受一个泛型Func,解决了我的大部分问题,但我不知道如何处理没有返回类型的情况 private T PerformApiCall<T>(RestRequest restRequest, Func<RestRequest, IRestResponse<T>> restMethod) {

我正在使用RestSharp库访问RESTAPI

我希望所有的API请求都通过相同的方法,这样我就可以在一个中心位置添加头、处理错误和其他事情

因此,我创建了一个方法,它接受一个泛型
Func
,解决了我的大部分问题,但我不知道如何处理没有返回类型的情况

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

    return response.Data;
}
private T调用(RestRequest RestRequest,Func restMethod)
{
var response=restMethod.Invoke(restRequest);
//处理错误
....
返回响应数据;
}
我这样称呼它:

var apples = PerformApiCall(new RestRequest('/api/apples'), req => Client.Execute<List<Apple>>(req));
var apples=PerformApiCall(新的RestRequest('/api/apples'),req=>Client.Execute(req));
但我遇到了一个问题,一堆API调用没有返回类型,因为它们不返回数据。因此,我使用了
Client.Execute(req)
,得到的错误是无法推断类型参数,我尝试传递,但失败了,因为它无法将非泛型
IRestResponse
转换为类型参数


有什么好办法解决这个问题吗?

您可以尝试的一件事是在
PerformApiCall
函数中添加一个重载,该函数使用非泛型结果类型的
Func
,但不返回任何结果:

// Notice the `Func` has `IRestResponse`, not `IRestResponse<T>`
public void PerformApiCall(RestRequest restRequest,
                           Func<RestRequest, IRestResponse> restMethod)
    ...
您收到了一个编译器错误,因为将子类型视为其超类型的实例是合理的,但将其视为另一个方向是不合理的(这是您将调用代码更改为just
Client.Execute(req)
,返回非泛型代码时发生的情况)


这里有一个ideone粘贴说明了这一点:

创建一个将
操作作为第二个参数的重载是否有帮助
private void PerformApiCall(RestRequest RestRequest,Action restMethod)
@robobot3000:我认为他仍然需要使用返回值(非泛型类型
IRestResponse
)来进行错误处理。如果他切换到
操作
,将无法访问响应。@voithos
没有返回类型,因为他们不返回数据
。如果没有返回任何内容,那么就没有什么用了。为什么不使用
Func
?@Madd0g有时我们试图以某种方式滥用代码,只是为了(上帝禁止)不违反枯燥的原则。看起来您的案例实际上有两个不同的需求,一个返回类型,另一个不返回。似乎完全适合使用重载。这是一个很好的解决方案,存在代码重用问题(我刚刚在OP中对此进行了评论),但很遗憾,我无法在其中一个方法中重用代码。如果没有更好的方法,我可能会这样做。我想了很多,这不是一个好的解决方案,因为我仍然需要调用
invoke
两次(泛型和非泛型),这意味着围绕调用复制逻辑(有错误处理,比如围绕调用进行try-and-catch,我无法抽象出来)@Madd0g:我编辑它是为了解决你提到的问题。这有点笨手笨脚,但使用泛型似乎是可行的。您还可以添加
where
子句来约束泛型。就清晰度而言,它是否更好,这可能取决于你要复制多少代码。我让它工作了,并且对它的外观和工作方式非常满意。谢谢@Madd0g我很好奇,你是模仿了voithos提出的精确解决方案还是想出了一些不同的方案?你能更新你的OP让我们看看它是什么样子吗?
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;