我想与您分享我根据 Ahmad Mageed 的工作得出的结论。(顺便说一句,这是一个很好的开始。)我需要相同的功能,但我需要它能够接受索引链中的更多深度。
这使您能够根据需要读取尽可能多的子索引,而无需对其进行硬编码以停止在 2 或 3 级深度。因此,通过此更新,您可以读取这样的查询字符串......
columns[0][data]=0&columns[0][name]=&columns[0][searchable]=true
&columns[0][orderable]=true&columns[0][search][value]=
&columns[0][search][regex]=false&columns[1][data]=1
&columns[1][name]=&columns[1][searchable]=true
&columns[1][orderable]=true&columns[1][search][value]=
&columns[1][search][regex]=false&columns[2][data]=2
...
&order[0][column]=0&order[0][dir]=asc&start=0&length=10&search[value]=&search[regex]=false
这是我对该部分代码的更新版本。
public IDictionary ConvertQueryString(string sQry)
{
string pattern = @"(?<Prop>[^[]+)(?:\[(?<Key>[^]]+)\])*=(?<Value>.*)";
// The brackets seem to be encoded as %5B and %5D
var qry = HttpUtility.UrlDecode(sQry);
var re = new Regex(pattern);
var dict = qry.Split(new[] { "?", "&" }, StringSplitOptions.RemoveEmptyEntries)
.Select(s => re.Match(s)).Where(g => g.Success)
.GroupBy(m => m.Groups["Prop"].Value)
.ToDictionary<IGrouping<string, Match>, string, object>(
g => g.Key,
g => GetKey(g, 0));
return dict;
}
private object GetKey(IGrouping<string, Match> grouping, int level)
{
var count = grouping.FirstOrDefault().Groups["Key"].Captures.Count;
// If the level is equal to the captures, then we are at the end of the indexes
if (count == level)
{
var gValue = grouping.Where(gr => gr.Success).FirstOrDefault();
var value = gValue.Groups["Value"].Value;
return value;
}
else
{
return grouping.Where(gr => gr.Success)
.GroupBy(m => m.Groups["Key"].Captures[level].Value)
.ToDictionary<IGrouping<string, Match>, string, object>(
a => a.Key,
a => GetKey(a, level + 1));
}
}
我想比仅仅构建一个嵌套字典对象更进一步,我想根据传递的字符串实际构建对象。我在新版本的 jQuery DataTables 中需要这个,它实际上是产生上面那个讨厌的查询字符串的原因。这是一个快速的写作,所以它有点粗糙并且可能有点容易出错,因为我还没有时间来强化它。
// Call it like so.
MyClass object = new MyClass();
WalkDictionary(dict, object);
// At this point the object will be filled out for you.
public class MyClass
{
public List<cColumns> columns { get; set; }
public cSearch search { get; set; }
}
public class cColumns
{
public int? data { get; set; }
public string name { get; set; }
public bool? searchable { get; set; }
public bool? orderable { get; set; }
public cSearch search { get; set; }
}
public class cSearch
{
public string value { get; set; }
public bool? regex { get; set; }
}
我只放了我需要的基本类型。因此,如果您需要/想要更多,那么您将不得不添加它们。
private void WalkDictionary(IDictionary dict, object obj)
{
foreach (string key in dict.Keys)
{
Type t = obj.GetType();
if (t.IsGenericType
&& typeof(List<>) == t.GetGenericTypeDefinition())
{
Type[] typeParameters = t.GetGenericArguments();
foreach (DictionaryEntry item in dict)
{
var lstPropObj = Activator.CreateInstance(typeParameters[0]);
WalkDictionary((IDictionary)item.Value, lstPropObj);
((IList)obj).Add(lstPropObj);
}
return;
}
PropertyInfo prop = obj.GetType().GetProperty(key);
if (prop == null)
continue;
if (dict[key] is IDictionary)
{
//Walk
var objProp = prop.GetValue(obj);
if (objProp == null)
objProp = Activator.CreateInstance(prop.PropertyType);
WalkDictionary(dict[key] as IDictionary, objProp);
prop.SetValue(obj, objProp);
}
else if (prop.PropertyType.IsAssignableFrom(typeof(int)))
{
int val = Convert.ToInt32(dict[key]);
prop.SetValue(obj, val);
}
else if (prop.PropertyType.IsAssignableFrom(typeof(bool)))
{
bool val = Convert.ToBoolean(dict[key]);
prop.SetValue(obj, val);
}
else if (prop.PropertyType.IsAssignableFrom(typeof(string)))
{
string val = Convert.ToString(dict[key]);
prop.SetValue(obj, val);
}
}
}