C# “如何重构”;使用;避免代码重复的语句?

C# “如何重构”;使用;避免代码重复的语句?,c#,wcf,refactoring,using-statement,C#,Wcf,Refactoring,Using Statement,假设我有以下方法: public string GetSchedules(string request) { using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint)) { return soapClient.GetSchedules(A

假设我有以下方法:

 public string GetSchedules(string request)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return soapClient.GetSchedules(AuthenticationInfo, request);
        }
    }

    public string GetCountryList(string request)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return soapClient.GetCountryList(AuthenticationInfo, request);
        }
    }

    public string GetCarriers(string request)
    {
        using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
        {
            return soapClient.GetCarriers(AuthenticationInfo, request);
        }
    }

正如您所看到的,唯一不同的是调用的方法的名称。我如何重构这些方法以只应用一次“using”语句并避免代码重复

那里真的没有太多的重复。尽管如此

public ServiceReference1.CustomDataTimetableToolKitServicesSoapClient NewClient()
{
    return new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint)
}

using (var client = NewClient()) {
    return soapClient.GetCountryList(AuthenticationInfo, request);
}

另外,由于所有方法都采用
string
参数并返回
string
,因此编写一个方法来调用它们很容易,将操作作为委托传递给调用。不幸的是,我现在没有时间为您写这篇文章。

您可以这样使用lambda函数:

public string GetCarriers(string request)
{
    return Get((authInfo, request) => soapClient.GetCarriers(authInfo, request), request);
}

...

public string Get(Func<AuthenticationInfo, string, string> action, string request) {
    using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
    {
        return action(AuthenticationInfo, request)
    }
}
publicstringgetcarriers(字符串请求)
{
返回Get((authInfo,request)=>soapClient.GetCarriers(authInfo,request),request);
}
...
公共字符串获取(Func操作、字符串请求){
使用(var soapClient=new ServiceReference1.CustomDataTimeTableToolKitsServicesSoapClient(EndpointConfigurationName,Endpoint))
{
返回操作(AuthenticationInfo,请求)
}
}
我不知道这是否合算,但你明白了

编辑: 正如@Tim S.所注意到的,此代码可能更短:

public string GetCarriers(string request)
{
    return Get(soapClient.GetCarriers, request);
}

...

public string Get(Func<AuthenticationInfo, string, string> action, string request) {
    using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
    {
        return action(AuthenticationInfo, request)
    }
}
publicstringgetcarriers(字符串请求)
{
返回Get(soapClient.GetCarriers,请求);
}
...
公共字符串获取(Func操作、字符串请求){
使用(var soapClient=new ServiceReference1.CustomDataTimeTableToolKitsServicesSoapClient(EndpointConfigurationName,Endpoint))
{
返回操作(AuthenticationInfo,请求)
}
}
编辑2:客户端超出范围。所以正确的代码是:

public string GetCarriers(string request)
{
    return Get((client, authInfo, request) => client.GetCarriers(authInfo, request));
}

...

public string Get(Func<ISoapClient, AuthenticationInfo, string, string> action, string request) {
    using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
    {
        return action(soapClient, AuthenticationInfo, request)
    }
}
publicstringgetcarriers(字符串请求)
{
返回Get((client,authInfo,request)=>client.GetCarriers(authInfo,request));
}
...
公共字符串获取(Func操作、字符串请求){
使用(var soapClient=new ServiceReference1.CustomDataTimeTableToolKitsServicesSoapClient(EndpointConfigurationName,Endpoint))
{
返回操作(soapClient、AuthenticationInfo、请求)
}
}

对我来说,你所拥有的一切都很好,但是如果你想把这些因素考虑进去,你可以使用
Func
和lambdas。大致如下:

public string GetSchedules(string request)
{
    return Worker((c) => c.GetSchedules(AuthenticationInfo, request));
}

public string GetCountryList(string request)
{
    return Worker((c) => c.GetCountryList(AuthenticationInfo, request));
}

public string GetCarriers(string request)
{
    return Worker((c) => c.GetCarriers(AuthenticationInfo, request));
}

private string Worker(Func<SoapClientClassGoesHere, string> f)
{
    using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
    {
        return f(soapClient);
    }
}

如果你的项目不是很大,你可以使用以下方法(有点乱,很容易出错):


我看不出这有什么帮助——事实上,如果它增加了一个方法的话?请注意,每个调用都指向不同的endpoint@JamesSugrue:它集中创建代理实例。不管它需要被创建,它将只在一个地方创建。维护地狱detected@SergeyBerezovskiy:为什么这会是一个维护问题?@JohnSaunders阅读和理解是其中的一部分maintenance@SergeyBerezovskiy:但有多少人需要阅读(并理解)该代码?此外,如果需要添加另一个方法,则该模式将很容易遵循。
(authInfo,request)=>soapClient.GetCarriers(authInfo,request)
通常可以替换为
soapClient.GetCarriers
您需要将
请求
传递给代理,因此您需要将其传递给
工作者
,您需要更新
Func
@JohnSaunders的签名:不,您不需要,lambda会关闭它:@t.J.Crowder非常感谢您,但是不同的响应类型呢?@moathnaji-如果您需要支持它们,您可以将
Worker
通用化:
私有t Worker(Func f){/*…*/}
(我想,这是我脑子里想不到的,我已经几个月没有做过C#generics了。)最佳做法是不要对WCF客户使用
using
语句-
using System;
using System.Collections.Generic;

class Foo {
    public string GetSchedules(string request)
    {
        return Worker((c) => c[request]);
    }

    public string GetCountryList(string request)
    {
        return Worker((c) => c[request].ToUpper());
    }

    public string GetCarriers(string request)
    {
        return Worker((c) => c[request].ToLower());
    }

    private string Worker(Func<Dictionary<string,string>, string> f)
    {
        var d = new Dictionary<string, string>();
        d.Add("1", "One");
        d.Add("2", "Two");
        d.Add("3", "Three");
        return f(d);
    }
}

public class Test
{
    public static void Main()
    {
        var f = new Foo();
        Console.WriteLine(f.GetSchedules("1"));
        Console.WriteLine(f.GetCountryList("1"));
        Console.WriteLine(f.GetCarriers("1"));
    }
}
public string getX (string request, string x)
{
    using (var soapClient = new ServiceReference1.CustomDataTimetableToolKitServicesSoapClient(EndpointConfiguratioName, Endpoint))
    {
        switch (x)
        {
            case "schedules":
                return soapClient.GetSchedules(AuthenticationInfo, request);
                break;
            case "countryList":
                return soapClient.GetCountryList(AuthenticationInfo, request);
                break;
            case "carriers":
                return soapClient.GetCarriers(AuthenticationInfo, request);
                break;
            }
        }
    }
}