在C#将匿名types转换为键/值数组?

我有以下匿名types:

new {data1 = "test1", data2 = "sam", data3 = "bob"} 

我需要一个方法将这个,并在数组或字典中输出键值对。

我的目标是使用这个作为HttpRequest中的发布数据,所以我最终将连接到以下string:

 "data1=test1&data2=sam&data3=bob" 

这只需要一点反思就能完成。

 var a = new { data1 = "test1", data2 = "sam", data3 = "bob" }; var type = a.GetType(); var props = type.GetProperties(); var pairs = props.Select(x => x.Name + "=" + x.GetValue(a, null)).ToArray(); var result = string.Join("&", pairs); 

如果您使用的是.NET 3.5 SP1或.NET 4,则可以使用RouteValueDictionary (ab) RouteValueDictionary实现此目的。 它实现了IDictionary<string, object>并有一个接受object并将属性转换为键值对的构造函数。

这将是微不足道的循环通过键和值来build立你的查询string。

这是他们如何在RouteValueDictionary中做到这一点:

  private void AddValues(object values) { if (values != null) { foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values)) { object obj2 = descriptor.GetValue(values); this.Add(descriptor.Name, obj2); } } } 

完整源代码在这里: http : //pastebin.com/c1gQpBMG

@ kbrimington的解决scheme是一个很好的扩展方法 – 我的例子返回一个HtmlString

  public static System.Web.HtmlString ToHTMLAttributeString(this Object attributes) { var props = attributes.GetType().GetProperties(); var pairs = props.Select(x => string.Format(@"{0}=""{1}""",x.Name,x.GetValue(attributes, null))).ToArray(); return new HtmlString(string.Join(" ", pairs)); } 

我使用它将任意属性放入Razor MVC视图。 我使用RouteValueDictionary开始使用代码,并在结果上循环,但是这样做很简单。

我做了这样的事情:

 public class ObjectDictionary : Dictionary<string, object> { /// <summary> /// Construct. /// </summary> /// <param name="a_source">Source object.</param> public ObjectDictionary(object a_source) : base(ParseObject(a_source)) { } /// <summary> /// Create a dictionary from the given object (<paramref name="a_source"/>). /// </summary> /// <param name="a_source">Source object.</param> /// <returns>Created dictionary.</returns> /// <exception cref="ArgumentNullException">Thrown if <paramref name="a_source"/> is null.</exception> private static IDictionary<String, Object> ParseObject(object a_source) { #region Argument Validation if (a_source == null) throw new ArgumentNullException("a_source"); #endregion var type = a_source.GetType(); var props = type.GetProperties(); return props.ToDictionary(x => x.Name, x => x.GetValue(a_source, null)); } } 

在@ GWBbuild议使用RouteValueDictionary ,我编写了这个recursion函数来支持嵌套的匿名types,并通过父键来嵌套这些嵌套参数。

 public static string EncodeHtmlRequestBody(object data, string parent = null) { var keyValuePairs = new List<string>(); var dict = new RouteValueDictionary(data); foreach (var pair in dict) { string key = parent == null ? pair.Key : parent + "." + pair.Key; var type = pair.Value.GetType(); if (type.IsPrimitive || type == typeof(decimal) || type == typeof(string)) { keyValuePairs.Add(key + "=" + HttpUtility.HtmlEncode(pair.Value).Replace(" ", "+")); } else { keyValuePairs.Add(EncodeHtmlRequestBody(pair.Value, key)); } } return String.Join("&", keyValuePairs); } 

用法示例:

 var data = new { apiOperation = "AUTHORIZE", order = new { id = "order123", amount = "101.00", currency = "AUD" }, transaction = new { id = "transaction123" }, sourceOfFunds = new { type = "CARD", provided = new { card = new { expiry = new { month = "1", year = "20" }, nameOnCard = "John Smith", number = "4444333322221111", securityCode = "123" } } } }; string encodedData = EncodeHtmlRequestBody(data); 

encodedData变成:

"apiOperation=AUTHORIZE&order.id=order123&order.amount=101.00&order.currency=AUD&transaction.id=transaction123&sourceOfFunds.type=CARD&sourceOfFunds.provided.card.expiry.month=1&sourceOfFunds.provided.card.expiry.year=20&sourceOfFunds.provided.card.nameOnCard=John+Smith&sourceOfFunds.provided.card.number=4444333322221111&sourceOfFunds.provided.card.securityCode=123"

希望这有助于其他人在类似的情况。