在C#中,是否可以重构我的帖子并使用方法消除代码重复?
我有以下两种方法:在C#中,是否可以重构我的帖子并使用方法消除代码重复?,c#,rest,functional-programming,refactoring,code-duplication,C#,Rest,Functional Programming,Refactoring,Code Duplication,我有以下两种方法: private string Post(string url, ByteArrayContent content, AuthenticationToken token = null) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; using HttpClient client = new HttpClient();
private string Post(string url, ByteArrayContent content, AuthenticationToken token = null) {
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using HttpClient client = new HttpClient();
if (token != null) {
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token);
}
return client.PostAsync(url, content)
.Result.Content.ReadAsStringAsync()
.Result;
}
private string Put(string url, ByteArrayContent content, AuthenticationToken token) {
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using HttpClient client = new HttpClient();
if (token != null) {
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token);
}
return client.PutAsync(url, content)
.Result.Content.ReadAsStringAsync()
.Result;
}
如您所见,唯一的区别是一个方法调用了PostAsync
,而另一个方法调用了PutAsync
是否可以编写一个函数,如:
private string Send(string url, ByteArrayContent content, AuthenticationToken token, String functionName) {
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using HttpClient client = new HttpClient();
if (token != null) {
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token);
}
return client[sendFunction](url, content)
.Result.Content.ReadAsStringAsync()
.Result;
}
然后我可以将其他每个函数转换为一行程序,如:
private string Post(string url, ByteArrayContent content, AuthenticationToken token = null) {
this.Send(url, content, token, "PostAsync");
}
。。。如果我能以一种类型安全的方式传递函数或函数名,那就更好了。您可以使用
开关
表达式。它在C#8中的功能令人惊讶。您可以在此处阅读更多内容并找到示例:
UPD:考虑使用枚举代替函数名来使代码类型化。
响应塞尔文的反应,我能想出:
private string Post(string url, ByteArrayContent content, AuthenticationToken token = null) {
return this.Send(token, (client) => client.PostAsync(url, content));
}
private string Put(string url, StringContent content, AuthenticationToken token) {
return this.Send(token, (client) => client.PutAsync(url, content));
}
private string Send(AuthenticationToken token, Func<HttpClient, Task<HttpResponseMessage>> sendFunction) {
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using HttpClient client = new HttpClient();
if (token != null) {
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Access_token);
}
return sendFunction(client)
.Result.Content.ReadAsStringAsync()
.Result;
}
private string Post(字符串url,ByteArrayContent内容,AuthenticationToken=null){
返回此.Send(令牌,(客户端)=>client.PostAsync(url,内容));
}
私有字符串Put(字符串url、StringContent内容、AuthenticationToken令牌){
返回this.Send(令牌,(客户端)=>client.PutAsync(url,内容));
}
私有字符串发送(AuthenticationToken令牌,Func sendFunction){
ServicePointManager.SecurityProtocol=SecurityProtocolType.Tls12;
使用HttpClient=new HttpClient();
if(令牌!=null){
client.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“Bearer”,token.Access\u token);
}
返回发送函数(客户端)
.Result.Content.ReadAsStringAsync()
.结果;
}
。。。这几乎就是我想要的,但我仍然需要表达“客户”两次
C#是否有任何符号允许我删除此冗余
或者我应该接受“尽可能好”吗?我假设由于某种原因,您不能使用
async/await
运算符
您可以这样减少冗余:
public static class Ext
{
public static string Finalize(this Task<HttpResponseMessage> httpResponseMessage)
{
return httpResponseMessage
.Result
.Content
.ReadAsStringAsync()
.Result;
}
}
public class Program
{
private string Post(string url, ByteArrayContent content, AuthenticationToken token = null)
{
return this.CreateClient(token)
.PutAsync(url, content)
.Finalize();
}
private string Put(string url, StringContent content, AuthenticationToken token)
{
return this.CreateClient(token)
.PostAsync(url, content)
.Finalize();
}
private HttpClient CreateClient(AuthenticationToken token)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using HttpClient client = new HttpClient();
if (token != null)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Value);
}
return client;
}
}
公共静态类Ext
{
公共静态字符串完成(此任务为httpResponseMessage)
{
返回httpResponseMessage
.结果
.内容
.ReadAsStringAsync()
.结果;
}
}
公共课程
{
私有字符串Post(字符串url、ByteArrayContent内容、AuthenticationToken token=null)
{
返回此.CreateClient(令牌)
.PutAsync(url、内容)
.Finalize();
}
私有字符串Put(字符串url、StringContent内容、AuthenticationToken令牌)
{
返回此.CreateClient(令牌)
.PostAsync(url、内容)
.Finalize();
}
私有HttpClient CreateClient(AuthenticationToken令牌)
{
ServicePointManager.SecurityProtocol=SecurityProtocolType.Tls12;
使用HttpClient=new HttpClient();
if(令牌!=null)
{
client.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载者”,token.Value);
}
返回客户;
}
}
因此,用一种方法包装客户端创建,并用扩展方法包装完成异步工作为响应干杯,但Robert Cecil Martin将交换机描述为一种讨厌的东西,如果必须使用,它应该深深地埋藏在代码中。:-)我正在寻找一种多态性的解决方案,或者至少可以在没有分支逻辑的情况下实现。但是罗伯特·塞西尔·马丁(Robert Cecil Martin)将交换机描述为一种令人憎恶的东西,如果必须使用它,它应该深深地埋藏在代码中。。。当你有
.Result.Content.ReadAsStringAsync().Result
的时候,这真是太有趣了,这是非常非常非常糟糕的。我承认这并不能让人愉快地阅读,但这是我必须使用的DSL。我可以提取一些变量,但我想不出任何名称可以在这个上下文中添加有用的信息。如果您有更好的方法,请告诉我。\n类似的事情。如果我可以简化用户端的参数,使其可以像Common(url、content、token、HttpClient.PutAsync)
那样表达,或者不需要对url和内容分别迭代三次,那就更好了。好吧,C#中没有“thiscall delegate”的概念。我想是的max@Selvin,为帮助干杯。我想我更喜欢我在下面所做的事情,虽然我仍然想看看是否有改进。。。。我会等一等,看看是否有人比我们任何一个人都清楚可以使用HttpClient.SendAsync
而不是PostAsync和PutAsync来删除冗余,只需提供HttpMethod.Post或HttpMethod.Put作为参数。@ckuri,这比删除冗余更划算,因为从那时起,我需要冗余地调用添加参数的代码。使用PostAsync和PutAsync更有表现力。我不喜欢静态方法,但这是一种有趣的方法。我不熟悉“this”关键字的用法,但我想我理解它。另一方面,我不完全清楚系统如何知道将Ext类应用于.Finalize()方法?我遗漏了什么吗?系统应用Ext类是因为它是扩展方法。你可以在这里读到更多关于它们的内容:如果我理解正确,这类似于其他语言可能称之为“特质”或“混合”的东西?但是C#如何知道将扩展类应用于程序类呢?我没有看到任何明确的声明。还是由Ext?static的可见性控制。。(this..)方法(extension method)在您使用的napespace中应用(当前od由using
应用),就像用新方法扩展预定义类型一样