C#中如何重构Post与Put方法消除代码重复并实现类型安全?
当然可以!而且有更类型安全的方案
你的思路完全正确——这两个方法的核心逻辑高度重复,绝对可以抽成通用方法来消除冗余。不过用字符串传递函数名的方式不太推荐,因为没有编译时检查,很容易打错字,后续重构也麻烦。我们可以用C#的委托来实现类型安全的代码复用,完美解决这个问题。
方案一:用委托封装HTTP方法调用
我们可以写一个通用的Send方法,把不同的HTTP请求逻辑(PostAsync/PutAsync)作为委托参数传进去,既保留类型安全,又彻底消除重复代码:
// 通用核心方法,处理公共逻辑 private string Send(string url, ByteArrayContent content, AuthenticationToken token, Func<HttpClient, string, ByteArrayContent, Task<HttpResponseMessage>> sendAction) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; using HttpClient client = new HttpClient(); if (token != null) { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token); } // 执行传入的HTTP请求操作 return sendAction(client, url, content) .Result.Content.ReadAsStringAsync() .Result; } // 简化后的Post方法 private string Post(string url, ByteArrayContent content, AuthenticationToken token = null) { return Send(url, content, token, (client, u, c) => client.PostAsync(u, c)); } // 简化后的Put方法 private string Put(string url, ByteArrayContent content, AuthenticationToken token) { return Send(url, content, token, (client, u, c) => client.PutAsync(u, c)); }
这里的Func<HttpClient, string, ByteArrayContent, Task<HttpResponseMessage>>是一个委托类型,它定义了“接受HttpClient、URL、内容三个参数,返回异步响应任务”的方法签名。我们用lambda表达式把PostAsync/PutAsync的逻辑传进去,完全是类型安全的,编译时就能检查出错误,比传字符串靠谱多了。
方案二:进一步优化(推荐异步实现)
另外,你原来的代码用.Result同步等待异步操作,在某些场景下可能导致死锁,更推荐遵循.NET异步最佳实践,改用async/await重构:
// 异步版通用核心方法 private async Task<string> SendAsync(string url, ByteArrayContent content, AuthenticationToken token, Func<HttpClient, string, ByteArrayContent, Task<HttpResponseMessage>> sendAction) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; using HttpClient client = new HttpClient(); if (token != null) { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token); } var response = await sendAction(client, url, content); return await response.Content.ReadAsStringAsync(); } // 异步版Post方法 private async Task<string> PostAsync(string url, ByteArrayContent content, AuthenticationToken token = null) { return await SendAsync(url, content, token, (client, u, c) => client.PostAsync(u, c)); } // 异步版Put方法 private async Task<string> PutAsync(string url, ByteArrayContent content, AuthenticationToken token) { return await SendAsync(url, content, token, (client, u, c) => client.PutAsync(u, c)); }
这样不仅消除了重复代码,还避免了同步阻塞的潜在问题,代码可读性也更强。
额外小优化
如果ServicePointManager.SecurityProtocol的设置不需要每次调用都执行(比如整个应用启动时设置一次就够),可以把这行代码移到应用初始化的地方,进一步精简方法内的重复逻辑。
内容的提问来源于stack exchange,提问作者Brian Kessler
相关产品推荐
相关产品推荐

