【问题标题】:Loop over (optional) method parameters循环(可选)方法参数
【发布时间】:2014-03-04 16:04:32
【问题描述】:

我正在编写一个简单的库,它提供对具有多个可选参数的 REST Web 服务的访问。

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);
        }
    }
    [...] 
}

这更适合一些,但我很好奇是否有更好的方法来解决此类问题,而无需创建长 if 语句或手动创建集合。

【问题讨论】:

  • 顺便说一下,一个有效的查询字符串是用&符号分隔的(&amp;),并以问号开头。
  • 已修复,感谢提示;)
  • 附带说明:您可能需要研究 ServiceStack (servicestack.net),它提供了创建 REST 应用程序的轻量级功能。

标签: c#


【解决方案1】:

这是一个选项:

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

【讨论】:

  • params 参数的类型必须(当前)是数组类型。 (未来的 C# 也有可能提供IEnumerable&lt;T&gt;params
  • 基本上是个好主意,但您会失去一点 IntelliSense 的便利性(显示和自动完成可用参数)。
【解决方案2】:

一种方法是使用匿名类型和反射,如下所示:

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);

    [...]
}

【讨论】:

    【解决方案3】:

    这是一个使用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"), 
                        });
    

    【讨论】:

    • 感谢您的意见。正如我对 T McKeown 所说,遗憾的是,您会失去一点 IntelliSense 便利性(显示和自动完成可用参数)。我想我会继续在方法中手动创建参数字典。
    【解决方案4】:

    根据 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;
    }
    

    【讨论】:

    • 您应该将此标记为答案。另外,不要忘记将System.Net.WebUtility.UrlEncode 用于您的parameter.Keyparameter.Value,否则如果它们中有一个& 符号或其他奇怪的字符,它们就会崩溃:)
    • 必须等待 24 小时才能将我自己的回复标记为答案。感谢 UrlEncode 的提示,这实际上非常有用:)
    【解决方案5】:

    这是我想出的。我在搞乱不做 a = null, b = null 参数的想法。

            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;
    
        }
    

    【讨论】:

      猜你喜欢
      • 2017-10-05
      • 2019-03-08
      • 2012-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 2015-05-17
      • 1970-01-01
      相关资源
      最近更新 更多