2014-03-03 73 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; 

    }