Dans c # convertir le type anonyme en tableau clé / valeur?

J’ai le type anonyme suivant:

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

J’ai besoin d’une méthode qui prendra cela en compte, et produira des paires de valeurs de clé dans un tableau ou un dictionnaire.

Mon but est de l’utiliser en tant que données de publication dans une requête HttpRequest, afin que je puisse concaténer dans la chaîne suivante:

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

Cela ne prend qu’un tout petit peu de reflection à accomplir.

 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 = ssortingng.Join("&", pairs); 

Si vous utilisez .NET 3.5 SP1 ou .NET 4, vous pouvez (ab) utiliser RouteValueDictionary pour cela. Il implémente IDictionary et dispose d’un constructeur qui accepte l’ object et convertit les propriétés en paires clé-valeur.

Il serait alors sortingvial de parcourir les clés et les valeurs pour construire votre chaîne de requête.

Voici comment ils le font dans 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); } } } 

La source complète est ici: http://pastebin.com/c1gQpBMG

La solution de @ kbrimington fait une belle méthode d’extension – mon dossier retourne un HtmlSsortingng

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

Je l’utilise pour déposer des atsortingbuts arbitraires dans une vue Razor MVC. J’ai commencé avec du code en utilisant RouteValueDictionary et en boucle sur les résultats mais c’est beaucoup plus net.

J’ai fait quelque chose comme ça:

 public class ObjectDictionary : Dictionary { ///  /// Construct. ///  /// Source object. public ObjectDictionary(object a_source) : base(ParseObject(a_source)) { } ///  /// Create a dictionary from the given object (). ///  /// Source object. /// Created dictionary. /// Thrown if  is null. private static IDictionary 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)); } } 

En s’appuyant sur la suggestion de @ GWB d’utiliser un RouteValueDictionary , j’ai écrit cette fonction récursive pour prendre en charge les types anonymes nesteds, en préfixant ces parameters nesteds par les clés de leurs parents.

 public static ssortingng EncodeHtmlRequestBody(object data, ssortingng parent = null) { var keyValuePairs = new List(); var dict = new RouteValueDictionary(data); foreach (var pair in dict) { ssortingng key = parent == null ? pair.Key : parent + "." + pair.Key; var type = pair.Value.GetType(); if (type.IsPrimitive || type == typeof(decimal) || type == typeof(ssortingng)) { keyValuePairs.Add(key + "=" + Uri.EscapeDataSsortingng((ssortingng)pair.Value).Replace("%20", "+")); } else { keyValuePairs.Add(EncodeHtmlRequestBody(pair.Value, key)); } } return Ssortingng.Join("&", keyValuePairs); } 

Exemple d’utilisation:

 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" } } } }; ssortingng encodedData = EncodeHtmlRequestBody(data); 

encodedData devient:

"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"

J’espère que cela aide quelqu’un d’autre dans une situation similaire.

Edit: Comme DrewG l’a souligné, cela ne prend pas en charge les tableaux. Implémenter correctement le support de tableaux arbitrairement nesteds avec des types anonymes ne serait pas sortingvial, et comme aucune des API que j’ai utilisées n’a accepté de tableaux non plus (je ne suis pas sûr qu’il existe une méthode standard de les sérialiser avec le codage de formulaire). Je vous laisse cela si vous avez besoin de les soutenir.

 using Newtonsoft.Json; var data = new {data1 = "test1", data2 = "sam", data3 = "bob"}; var encodedData = new FormUrlEncodedContent(JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(data)) 

Il existe une méthode intégrée de conversion d’objects anonymes en dictionnaires:

 HtmlHelper.AnonymousObjectToHtmlAtsortingbutes(yourObj) 

Il renvoie également RouteValueDictionary . Notez que c’est statique