it-swarm.com.de

In c # anonymen Typ in ein Schlüssel/Wert-Array konvertieren?

Ich habe den folgenden anonymen Typ:

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

Ich brauche eine Methode, die dies übernimmt und Schlüsselwertpaare in einem Array oder Wörterbuch ausgibt. 

Mein Ziel ist es, diese Daten als Postdaten in einem HttpRequest zu verwenden, so dass ich schließlich in der folgenden Zeichenfolge verketten kann:

"data1=test1&data2=sam&data3=bob"
72
Chris Kooken

Dies erfordert nur ein wenig Nachdenken.

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);
107
kbrimington

Wenn Sie .NET 3.5 SP1 oder .NET 4 verwenden, können Sie RouteValueDictionary (ab) verwenden. Es implementiert IDictionary<string, object> und verfügt über einen Konstruktor, der object akzeptiert und Eigenschaften in Schlüsselwertpaare konvertiert.

Es wäre dann trivial, die Schlüssel und Werte zu durchlaufen, um Ihre Abfragezeichenfolge zu erstellen.

61
GWB

So machen sie das 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);
            }
        }
    }

Vollständige Quelle ist hier: http://Pastebin.com/c1gQpBMG

25
John

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));
    }
}
1
Jordan

Aufbauend auf dem Vorschlag von @ GWB, eine RouteValueDictionary zu verwenden, habe ich diese rekursive Funktion geschrieben, um verschachtelte anonyme Typen zu unterstützen, wobei den 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);
}

Verwendungsbeispiel:

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 zu:

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

Edit: Wie DrewG darauf hinweist, unterstützt dies keine Arrays. Die Unterstützung für willkürlich verschachtelte Arrays mit anonymen Typen ordnungsgemäß zu implementieren, wäre nicht trivial, und da keine der von mir verwendeten APIs Arrays akzeptiert hat (ich bin nicht sicher, ob es eine standardisierte Möglichkeit gibt, sie mit Formularkodierung zu serialisieren) Das überlasse ich Ihnen, wenn Sie sie unterstützen müssen.

1
Extragorey

@ kbrimingtons Lösung macht eine Nice-Erweiterungsmethode - mein Fall, in dem ein HtmlString zurückgegeben wird

    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 eine MVC-Ansicht von Razor abzulegen. Ich habe mit Code begonnen, der RouteValueDictionary verwendet und die Ergebnisse in einer Schleife abläuft, aber das ist viel netter.

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

Es gibt eine integrierte Methode zum Konvertieren anonymer Objekte in Wörterbücher:

HtmlHelper.AnonymousObjectToHtmlAttributes(yourObj)

Es gibt auch RouteValueDictionary zurück. Beachten Sie, dass es statisch ist

0
Xymanek