здания на @ предложение GWB о использовании RouteValueDictionary
, я написал эту рекурсивную функцию для поддержки вложенных анонимных типов, предваряя эти вложенные параметры с помощью клавиш их родителей.
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);
}
Пример использование:
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"
Надеется, что это помогает кто-то в подобной ситуации.
Редактировать: Как указал DrewG, это не поддерживает массивы. Правильно реализовать поддержку произвольно вложенных массивов с анонимными типами было бы нетривиальным, и поскольку ни один из API-интерфейсов, которые я использовал, не принял также массивы (я не уверен, что существует даже стандартизованный способ сериализации их с кодировкой формы) Я оставлю это вам, если вам нужно их поддержать.
вар ДИКТ = props.ToDictionary (х => x.Name, х => x.GetValue (a_source, нуль)) – Jordan
Мы получили это далеко ... мы можем сделать его один вкладыш: 'уаг dict = a.GetType(). GetProperties().ToDictionary (x => x.Name, x => x.GetValue (a, null)); ' – kape123
@ kape123, действительно. На самом деле, последние версии .NET больше не требуют вызова 'ToArray()', что приятно. Во всяком случае, ответ, который он стоит, прекрасно вписывается в SO без переноса слов, поэтому я оставлю его как есть. – kbrimington