如何重构 "using" 语句以避免代码重复?
How to refactor "using" statement to avoid code duplication?
假设我有以下方法:
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
参数和 return 一个 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)
}
}
我不知道这是否编译,但你明白了。
编辑:
正如@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)
}
}
编辑 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)
}
}
对我来说,你所拥有的很好,但如果你想将它们排除在外,你可以使用 Func
和 lambda。沿着这些线的东西:
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);
}
}
Func<A, R>
表示 "a function that takes an argument of type A
and returns a value of type R
"(对于接受 两个 参数等的函数,您可以使用 Func<A, B, R>
)。
更多关于 Func<>
和 this question and this question 中的 lambda 的信息(以及更多,这是一个内容丰富的主题)。
这是一个 live example on ideone.com(一个非常愚蠢的实例,但它演示了这个概念):
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;
}
}
}
}
假设我有以下方法:
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
参数和 return 一个 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)
}
}
我不知道这是否编译,但你明白了。
编辑: 正如@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)
}
}
编辑 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)
}
}
对我来说,你所拥有的很好,但如果你想将它们排除在外,你可以使用 Func
和 lambda。沿着这些线的东西:
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);
}
}
Func<A, R>
表示 "a function that takes an argument of type A
and returns a value of type R
"(对于接受 两个 参数等的函数,您可以使用 Func<A, B, R>
)。
更多关于 Func<>
和 this question and this question 中的 lambda 的信息(以及更多,这是一个内容丰富的主题)。
这是一个 live example on ideone.com(一个非常愚蠢的实例,但它演示了这个概念):
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;
}
}
}
}