2014-03-03 34 views
2

我正在写一个简单的库,它提供对具有多个可选参数的REST Webservice的访问。循环(可选)方法参数

Sample URL: 
http://localhost/doSomething?a=a&b=b&c=c 

所以我的出发点是一个带可选参数的方法。像这样:

public byte[] DoSomething(string a = null, string b = null, string c = null) 
{ 
    string query = "doSomething"; 
    //Get Parameters 
    if (a != null) 
    { 
     //Handle first ? 
     query = String.Format("{0}&{1}={2}", query, "a", a); 
    } 
    [...] 
} 

你可以想象,如果你有很多参数,这会导致一个很长的方法。减少代码大小的一种方式是各参数添加到集合:

public byte[] DoSomething(string a = null, string b = null, string c = null) 
{ 
    string query = "doSomething"; 
    var parameters = new Dictionary<string, string> {{"a", a}, {"b", b}, {"c", c}}; 
    foreach (var parameter in parameters) 
    { 
     if (!String.IsNullOrEmpty(parameterPair.Value)) 
     { 
      //Handle first ? 
      query = String.Format("{0}&{1}={2}", query, parameter.Key, parameter.Value); 
     } 
    } 
    [...] 
} 

这是更suiteable了一点,但我很好奇,如果有解决上述问题的一个更好的方法,而无需创建更长久语句或手动创建集合。

+1

顺便说一句,一个有效的查询字符串用&符号('&')分开,并以问号开头。 – Diamondo25

+0

固定,谢谢你的提示;) –

+0

只是一个侧面说明:你可能想看看ServiceStack(https://servicestack.net/),它提供了一个轻量级的能力来创建REST应用程序。 – Samuel

回答

1

根据T McKeown,Nasreddine和John Gibb的回答,我想出了一个“ParameterModel”。有WebService方法,基本上有相同的参数+一些额外的,所以我想出了这种方式来使用继承。

public class BaseABCModel 
{ 
    public string A { get; set; } 
    public string B { get; set; } 
    public string C { get; set; } 

    public BaseABCModel(string a = null, string b = null, string c = null) 
    { 
     A = a; 
     B = b; 
     C = c; 
    } 

    public Dictionary<string, string> GetParameters() 
    { 
     return GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance) 
     .ToDictionary(propertyInfo => propertyInfo.Name, propertyInfo => 
     (String) propertyInfo.GetValue(this)); 
    } 
} 


//Methods: 
public byte[] DoSomething(BaseABCModel model) 
{ 
    string query = GetQuery("doSomething", model.GetParameters()) 
} 


public string GetQuery(string methodName, Dictionary<string, string> parameters) 
{ 
    string parameterString = parameters.Where(parameter => !String.IsNullOrEmpty(parameter.Value)) 
    .Aggregate(String.Empty, (current, parameter) => String.Format(
    String.IsNullOrEmpty(current) ? "{0}?{1}={2}" : "{0}&{1}={2}", 
    current, parameter.Key, parameter.Value)); 

    return methodName + parameterString; 
} 
+0

你应该标记这个答案。另外,不要忘记为你的'parameter.Key'和'parameter.Value'使用'System.Net.WebUtility.UrlEncode',否则如果它们中有一个&符或其他奇怪的字符,它们就会崩溃: ) –

+0

必须等待24小时才能将自己的答复标记为答案。感谢与UrlEncode提示,这实际上非常有用:) –

1

这是一个选项:

public byte[] DoSomething(Tuple<string,string>[] kvp) 
{ 
... 
} 
+2

'params'参数的类型必须(当前)是一个数组类型。 (有一些可能性,未来的C#可能会提供'IEnumerable '' params'也) –

+0

该死的,你是对的...我将它改为Tuple <> –

+0

基本上是一个好主意,但是你会失去一点智能感知的便利显示和自动完成可用参数)。 –

1

一种方法是使用匿名类型和反映,像这样:

public byte[] DoSomething(string a = null, string b = null, string c = null) 
{ 
    var p = new { a, b, c }; 
    var parts = from property in p.GetType().GetProperties() 
       let value = property.GetValue(p) as string 
       where !string.IsNullOrEmpty(value) 
       select string.Format("{0}={1}", property.Name, value); 

    var query = "?" + string.Join("&", parts); 

    [...] 
} 
1

下面是一个使用params一个例子:

byte[] DoSomething(params KeyValuePair<string, string>[] parameters) 
{ 
    var builder = new StringBuilder(); 
    for (int i = 0; i < parameters.Length; i++) 
    { 
     builder.AppendFormat("{0}={1}", parameters[i].Key, parameters[i].Value); 
     if (i != parameters.Length - 1) 
     { 
      builder.Append("&"); 
     } 
    } 
    string urlParams = builder.ToString(); // contains "param1=value1&param2=value2" 
    ... 
} 

以下是如何使用它:

DoSomething(new[] { 
        new KeyValuePair<string, string>("param1", "value1"), 
        new KeyValuePair<string, string>("param2", "value2"), 
        }); 
+0

感谢您的支持。正如我对T McKeown所说的,不幸的是,你会失去一点智能感知的便利(可用参数的显示和自动完成)。我想我会留在方法内手动创建参数字典。 –

0

这是我想出来的。我搞乱了不做a = null,b = null params的想法。

 public byte[] mainoutput(string text) 
    { 

     byte[] retval = null; 

     char[] delimeterChars = { '?' }; 

     string[] newparsm = text.Split(delimeterChars); 
     string query = ""; 
     int count = 0; 

     foreach (string s in newparsm) 
     { 
      count += 1; 

      if (s.Length > 2) 
      { 
       if (count == 1) 
       { 
        query = query + "?" + s; 
       } 
       else 
       { 
        query = query + "&" + s; 
       } 
      } 

     } 
     Console.WriteLine(query); 

     return retval; 

    }