Domanda

È possibile in C # creare un System.Collections.Generic.Dictionary<TKey, TValue> dove TKey è una classe incondizionata e TValue - una classe anonima con un numero di proprietà, ad esempio il nome della colonna del database e il nome localizzato.

Qualcosa del genere:

new { ID = 1, Name = new { Column = "Dollar", Localized = "Доллар" } }
È stato utile?

Soluzione

Non puoi dichiarare un tale tipo di dizionario direttamente (ci sono kludges ma questi sono solo a scopo di intrattenimento e novità), ma se i tuoi dati provengono da una fonte IEnumerable o IQueryable, puoi ottenerne uno usando l'operatore LINQ ToDictionary e proiettando la chiave richiesta e il valore (digitato in modo anonimo) dagli elementi della sequenza:

var intToAnon = sourceSequence.ToDictionary(
    e => e.Id,
    e => new { e.Column, e.Localized });

Altri suggerimenti

Come itowlson ha detto , non puoi dichiarare una tale bestia, ma puoi davvero crearla :

static IDictionary<TKey, TValue> NewDictionary<TKey, TValue>(TKey key, TValue value)
{
    return new Dictionary<TKey, TValue>();
}

static void Main(string[] args)
{
    var dict = NewDictionary(new {ID = 1}, new { Column = "Dollar", Localized = "Доллар" });
}

Non è chiaro il motivo per cui vorresti effettivamente utilizzare il codice in questo modo.

Penso che ASP.NET MVC non sia uscito al momento in cui è stata posta questa domanda. Converte internamente oggetti anonimi in dizionari.

Dai un'occhiata alla HtmlHelper class , per esempio. Il metodo che traduce gli oggetti in dizionari è AnonymousObjectToHtmlAttributes . È specifico per MVC e restituisce un RouteValueDictionary, tuttavia.

Se vuoi qualcosa di più generico, prova questo:

public static IDictionary<string,object> AnonymousObjectToDictionary(object obj)
{
    return TypeDescriptor.GetProperties(obj)
        .OfType<PropertyDescriptor>()
        .ToDictionary(
            prop => prop.Name,
            prop => prop.GetValue(obj)
        );
}

Un vantaggio interessante di questa implementazione è che restituisce un dizionario vuoto per null oggetti.

Ed ecco una versione generica:

public static IDictionary<string,T> AnonymousObjectToDictionary<T>(
    object obj, Func<object,T> valueSelect
)
{
    return TypeDescriptor.GetProperties(obj)
        .OfType<PropertyDescriptor>()
        .ToDictionary<PropertyDescriptor,string,T>(
            prop => prop.Name,
            prop => valueSelect(prop.GetValue(obj))
        );
}

Puoi fare una riflessione

public static class ObjectExtensions
{
    /// <summary>
    /// Turn anonymous object to dictionary
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public static IDictionary<string, object> ToDictionary(this object data)
    {
        var attr = BindingFlags.Public | BindingFlags.Instance;
        var dict = new Dictionary<string, object>();
        foreach (var property in data.GetType().GetProperties(attr))
        {
            if (property.CanRead)
            {
                dict.Add(property.Name, property.GetValue(data, null));
            }
        }
        return dict;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top