2012-04-19 80 views
0

我有一个接收字符串的Web服务。检查存储在字典中的参数是否有效

该字符串包含多个键=>与字符“+”连接的值。

我必须验证每个值(“required”,“not empty”),并将每个值赋给一个具有相同名称的变量。

这里是我从字符串建立词典:

string firstname; 
string lastname; 
string amount; 

string request = "firstname=foo+lastname=bar+amout=100.58"; 

Dictionary<string, string> arguments = new Dictionary<string, string>(); 

request.Split('+').ToList<string>().ForEach(p => 
{ 
    string[] tmp = p.Split('='); 

    if (tmp.Length == 2) 
     arguments.Add(tmp[0], tmp[1]); 
}); 

// Validate and assign : How I do with one value : (I must find a better way) 
bool isValid = true; 

// check "firstname" 
if(arguments.ContainsKey("firstname") && string.IsNullOrWhiteSpace(arguments["firstname"]) == false) 
{ 
    firstname = arguments["firstname"]; 
} 
else 
{ 
    isValid = false; 
    Logger.Write("Invalid argument : firstname"); 
} 

// Do this for about 20 arguments, it becomes huge... 

if(isValid) 
{ 
    Console.WriteLine(firstname); // Displays foo 
    Console.WriteLine(lastname); // Displays bar 
    Console.WriteLine(amout); // Displays 100.58 
} 

感谢,并为拼写错误对不起,我是法国人。

+2

HM ..什么是真正的问题? – Tigran 2012-04-19 14:35:39

+0

你想要有效吗? – 2012-04-19 14:36:36

+0

例如,我不知道如何检查字典中是否存在firstname,如果它不是空的,以及如何用变量值填充变量“firstname”。事实上,大约有20个参数,验证每个参数变得非常巨大。 – 2012-04-19 14:42:41

回答

0

认为你想是这样的,但因为你没有实际上可以问一个问题,我只是猜测:

request.Split('+').ToList<string>().ForEach(p => 
{ 
    string[] tmp = p.Split('='); 

    if (tmp.Length == 2 && !string.IsNullOrWhiteSpace(tmp[1])) 
    { 
     // edit - if your string can have duplicates, use 
     // Dictionary<U,K>.ContainsKey(U) to check before adding 
     var key = tmp[0]; 
     var value = tmp[1]; 

     if(!arguments.ContainsKey(key)) 
     { 
      arguments.Add(key, value); 
     } 
     else 
     { 
      //overwrite with new value 
      //could also maybe throw on duplicate or some other behavior. 
      arguents[key]=value; 
     } 
    } 
    else 
     throw InvalidOperationException("Bad dictionary string value"); 
}); 

另外,我会质疑,如果使用ToList->的foreach这是在我面前的代码审查。你要避免在LINQ的副作用,我将它与传统的foreach这样写:

var itemValues = request.Split('+'); 
foreach(var item in itemValues) 
{ 
    string[] tmp = item.Split('='); 

    if (tmp.Length == 2 && !string.IsNullOrWhiteSpace(tmp[1])) 
     arguments.Add(tmp[0], tmp[1]); 
    else 
     throw InvalidOperationException("Bad dictionary string value"); 
}); 



// Validate and assign 
//read values from the dictionary 
//use ContainsKey to check for exist first if needed 

Console.WriteLine(arguments["firstname"]); // Displays foo 
Console.WriteLine(arguments["lastname"]); // Displays foo 
Console.WriteLine(arguments["amout"]); // Displays 100.58 

编辑2 - 你应该封装逻辑的方法:

private string TryGetValue(IDictionary<string,string> dict,string key) 
{ 
    string value = null; 
    if(dict.ContainsKey(key) && !string.IsNullOrWhiteSpace(dict[key])) 
    { 
     value = dict[key]; 
    } 
    else 
    { 
     Logger.Write("Invalid argument : " + key); 
    } 
    return value; 
} 

现在,你可以说:

string firstName = TryGetValue(arguments,"firstname"); 
string lastName= TryGetValue(arguments,"lastName"); 
string amount = TryGetValue(arguments,"amount"); 

bool isValid = firstName!=null && lastName != null && amount != null; 

if(isValid) 
{ 
    Console.WriteLine(firstName); // Displays foo 
    Console.WriteLine(lastName); // Displays bar 
    Console.WriteLine(amout); // Displays 100.58 
} 

TryGetValue会成为一个优秀的扩展方法:

public static class Extensions 
{ 
    public static string TryGetValue(this IDictionary<string,string> dict, string key) 
    { 
     string value = null; 
     if(dict.ContainsKey(key) && !string.IsNullOrWhiteSpace(dict[key])) 
     { 
      value = dict[key]; 
     } 
     else 
     { 
      Logger.Write("Invalid argument : " + key); 
     } 
     return value; 
    } 

} 

现在调用代码看起来像:

string firstName = arguments.TryGetValue("firstname"); 
string lastName= arguments.TryGetValue("lastname"); 
string amount = arguments.TryGetValue("amount"); 

最后编辑 - 了一份关于extention方法 - 是的,他们是整齐的,但它也很容易在恶劣的情况下过度使用他们意外地得到。阅读关于他们的msdn和博客,请遵循指导原则。避免像objectstring等通用类型的扩展。

在我的项目,我总是奠定了在根据他们交往的类型,这迫使那些希望利用它们来为类不同的命名空间的扩展方法很阐明它想:

namespace Extensions.IDictionary { ... } 
namespace Extensions.string { ... } 
namespace Extensions.SomeType { ... } 
namespace Extensions.IList { ... } 

和消费码本来using条款相匹配:

using Extensions.IDictionary; 

拉在只是扩展你的兴趣,没了。

+0

非常感谢,我是c#新手,我不知道扩展方法。很酷的功能! – 2012-04-19 15:17:04

+0

@AsKaiser没问题!将来请尽可能提供尽可能多的信息来写出您的问题,以避免混淆。没有人喜欢猜测!我也为你添加了关于扩展方法的简短注释。 – asawyer 2012-04-19 15:22:49

0

这只是一个猜测,因为你的问题并不清楚。

// Validate and assign 

foreach(KeyValuePair<string,string> pair in arguments) 
{ 
    if(!String.IsNullOrEmpty(pair.Value)) 
    { 
     Console.WriteLine(pair.Value); 
    } 
} 
0

如果您有更多然后只是一个名字和姓氏,并且,您可以使用一个列表作为字典的值。 这样,您可以简单地为名,姓和其他值添加其他值。

要验证,你可以将它添加值到字典之间:

string request = "firstname=foo+lastname=bar+amout=100.58+firstname=+lastname=bar2+amout=100.59+firstname=foo3+lastname3=bar3+amout=100.60"; 

     Dictionary<string, List<string>> arguments = new Dictionary<string, List<string>>(); 
     request.Split('+').ToList<string>().ForEach(f => 
      { 
       string[] data = f.Split('='); 
       if (data.Length == 2) 
       { 
        if (!arguments.ContainsKey(data[0])) 
        { 
         if (data[1] != "") 
          arguments.Add(data[0], new List<string> { data[1] }); 
         else 
          arguments.Add(data[0], new List<string> { "no firstname" }); 
        } 
        else 
        { 
         if (data[1] != "") 
          arguments[data[0]].Add(data[1]); 
         else 
          arguments[data[0]].Add("no firstname"); 
        } 
       } 
      }); 

希望它能帮助, 再见