在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
应用),就像用新方法扩展预定义类型一样