Ich habe den folgenden anonymen Typ:
new {data1 = "test1", data2 = "sam", data3 = "bob"}
Ich benötige eine Methode, die dies berücksichtigt und Schlüsselwertpaare in einem Array oder Wörterbuch ausgibt.
Mein Ziel ist es, dies als Post-Daten in einer HttpRequest zu verwenden, damit ich sie schließlich in die folgende Zeichenfolge verketten kann:
"data1=test1&data2=sam&data3=bob"
c#
.net
httpwebrequest
anonymous-types
Chris Kooken
quelle
quelle
var dict = a.GetType().GetProperties().ToDictionary(x => x.Name, x => x.GetValue(a, null));
ToArray()
, was sehr schön ist. Auf jeden Fall passt die Antwort in ihrer jetzigen Form gut in SO ohne Zeilenumbruch, also lasse ich sie so wie sie ist.Wenn Sie .NET 3.5 SP1 oder .NET 4 verwenden, können Sie dies (ab) verwenden
RouteValueDictionary
. Es implementiertIDictionary<string, object>
und verfügt über einen Konstruktor,object
der Eigenschaften akzeptiert und in Schlüssel-Wert-Paare konvertiert.Es wäre dann trivial, die Schlüssel und Werte zu durchlaufen, um Ihre Abfragezeichenfolge zu erstellen.
quelle
HtmlHelper
Erweiterungsmethoden.So machen sie es in 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); } } }
Die vollständige Quelle finden Sie hier: http://pastebin.com/c1gQpBMG
quelle
Es gibt eine integrierte Methode zum Konvertieren anonymer Objekte in Wörterbücher:
Es kehrt auch zurück
RouteValueDictionary
. Beachten Sie, dass es statisch istquelle
using Newtonsoft.Json; var data = new {data1 = "test1", data2 = "sam", data3 = "bob"}; var encodedData = new FormUrlEncodedContent(JsonConvert.DeserializeObject<Dictionary<string, string>>(JsonConvert.SerializeObject(data))
quelle
Die Lösung von @ kbrimington ist eine nette Erweiterungsmethode - mein Fall ist die Rückgabe eines HTML-Strings
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)); }
Ich verwende es, um beliebige Attribute in einer Razor MVC-Ansicht abzulegen. Ich habe mit Code angefangen, der RouteValueDictionary verwendet und die Ergebnisse wiederholt, aber das ist viel ordentlicher.
quelle
HtmlHelper.AnonymousObjectToHtmlAttributes
Ich habe so etwas gemacht:
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)); } }
quelle
Aufbauend auf dem Vorschlag von @ GWB, a zu verwenden
RouteValueDictionary
, habe ich diese rekursive Funktion geschrieben, um verschachtelte anonyme Typen zu unterstützen, wobei diesen verschachtelten Parametern die Schlüssel ihrer Eltern vorangestellt werden.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 + "=" + Uri.EscapeDataString((string)pair.Value).Replace("%20", "+")); } else { keyValuePairs.Add(EncodeHtmlRequestBody(pair.Value, key)); } } return String.Join("&", keyValuePairs); }
Anwendungsbeispiel:
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
wird:"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"
Hoffe das hilft jemand anderem in einer ähnlichen Situation.
Bearbeiten: Wie DrewG betonte, unterstützt dies keine Arrays. Die ordnungsgemäße Implementierung der Unterstützung für beliebig verschachtelte Arrays mit anonymen Typen wäre nicht trivial, und da keine der von mir verwendeten APIs Arrays akzeptiert hat (ich bin nicht sicher, ob es überhaupt eine standardisierte Methode gibt, sie mit Formularcodierung zu serialisieren). Ich überlasse das euch, wenn ihr sie unterstützen müsst.
quelle
Es ist zu spät, aber ich würde dies für eine robustere Lösung hinzufügen. Diejenigen, die ich hier sehe, haben einige Probleme (als würden sie mit DateTime nicht richtig funktionieren). Aus diesem Grund schlage ich vor, zuerst in einen JSON (Newtonsoft Json.Net) zu konvertieren:
var data = new {data1 = "test1", data2 = "sam", data3 = "bob"}; var result = string.Join("&", JsonConvert.DeserializeObject<Dictionary<string, string>>( JsonConvert.SerializeObject(data)) .Select(x => $"{x.Key}={x.Value}") );
quelle