请告诉我,我应该如何修改这段代码,这样就不会有太多的复制/粘贴了?有没有办法把泛型称为非泛型?我应该把<object>
传递给泛型并对此感到满意吗?最好的解决方案是什么?
我举个例子
public interface IHttpService
{
Task<T> Post<T>(string uri, HttpContent content, int timeOut = 100, CancellationToken token = default);
Task Post(string uri, HttpContent content, int timeOut = 100, CancellationToken token = default);
}
因此它们具有几乎相同但不同实现
public async Task Post(string uri, HttpContent content, int timeOut = 100, CancellationToken token = default)
{
var request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = content;
await sendRequest(request, timeOut, token);
}
public async Task<T> Post<T>(string uri, HttpContent content, int timeOut = 100, CancellationToken token = default)
{
var request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = content;
return await sendRequest<T>(request, timeOut, token);
}
private async Task sendRequest(HttpRequestMessage request, int timeOut = 100, CancellationToken token = default)
{
try
{
using var requestCTS = new CancellationTokenSource(TimeSpan.FromSeconds(timeOut));
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(requestCTS.Token, token);
using var response = await _httpClient.SendAsync(request, linkedCts.Token);
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync(token);
throw new Exception(error);
}
}
private async Task<T> sendRequest<T>(HttpRequestMessage request, int timeOut = 100, CancellationToken token = default)
{
try
{
using var requestCTS = new CancellationTokenSource(TimeSpan.FromSeconds(timeOut));
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(requestCTS.Token, token);
using var response = await _httpClient.SendAsync(request, linkedCts.Token);
if (!response.IsSuccessStatusCode)
{
var error = await response.Content.ReadAsStringAsync(token);
throw new Exception(error);
}
return (await response.Content.ReadFromJsonAsync<T>())!;
}
更新
private async Task<HttpContent> sendRequest(HttpRequestMessage request, int timeOut = 100, CancellationToken token = default)
{
try
{
using var requestCTS = new CancellationTokenSource(TimeSpan.FromSeconds(timeOut));
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(requestCTS.Token, token);
using var response = await _httpClient.SendAsync(request, linkedCts.Token);
if (!response.IsSuccessStatusCode)
{
await response.Content.ReadAsStringAsync(token);
throw new Exception(error);
}
return response.Content;
}
catch (AccessTokenNotAvailableException)
{
_navigationManager.NavigateToLogout(StaticStringHelper.LogoutPatch);
return default(HttpContent)!;
}
}
当我用它的时候
public async Task<T> Get<T>(string uri, int timeOut = 100, CancellationToken token = default)
{
var request = new HttpRequestMessage(HttpMethod.Get, uri);
return await (await sendRequest(request, timeOut, token)).ReadFromJsonAsync<T>(cancellationToken: token);
}
我得到
microsoft.AspNetCore. Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Cannot access a disposed object.
Object name: 'System.Net.Http.BrowserHttpContent'.
System. ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Http.BrowserHttpContent'.
at System.Net.Http.HttpContent.CheckDisposed()
at System.Net.Http.HttpContent.ReadAsStreamAsync(CancellationToken cancellationToken)
1条答案
按热度按时间tcomlyy61#
c#中没有泛型“void”,在某些情况下你可以使用一个泛型,用int或者bool作为一个无意义的值,在其他情况下你只能忍受它,保留两个实现。
在这个特殊的例子中,唯一的区别似乎是
response.Content.ReadFromJsonAsync<T>()
,所以你应该能够重构它,使所有其他代码通用。由于内容被释放,你需要使用一个委托来注入不同的代码:c => Task.FromResult(0)
只是为了适应泛型类型,“0”值从未在任何地方使用过。