c# - caracteristicas - ventajas bases de datos clave valor




¿En c#convierte el tipo anónimo en matriz de clave/valor? (5)

Aquí es cómo lo hacen en 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);
            }
        }
    }

Fuente completa está aquí: http://pastebin.com/c1gQpBMG

Tengo el siguiente tipo anónimo:

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

Necesito un método que lo incorpore y genere pares de valores clave en una matriz o diccionario.

Mi objetivo es usar esto como datos de publicación en HttpRequest, así que finalmente concatenaré en la siguiente cadena:

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

Esto requiere solo un poquito de reflexión para lograrlo.

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

La solución de @ kbrimington es un buen método de extensión: mi caso es devolver un 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));
    }

Lo estoy usando para colocar atributos arbitrarios en una vista de Razor MVC. Comencé con el código usando RouteValueDictionary y haciendo un bucle en los resultados, pero esto es mucho más ordenado.


Partiendo de la sugerencia de RouteValueDictionary de utilizar un RouteValueDictionary , escribí esta función recursiva para admitir tipos anónimos anidados, prefijando esos parámetros anidados con las claves de sus padres.

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

Ejemplo de uso:

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 convierte en:

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

Espero que esto ayude a alguien más en una situación similar.

Editar: como señaló DrewG, esto no admite matrices. Implementar adecuadamente el soporte para matrices anidadas arbitrariamente con tipos anónimos no sería trivial, y como ninguna de las API que he usado también acepta matrices (no estoy seguro de que haya incluso una forma estandarizada de serializarlas con codificación de formularios), Les dejaré eso a ustedes si necesitan apoyarlos.


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




anonymous-types