Словарь, где значение является анонимным типом в C # - PullRequest
36 голосов
/ 25 октября 2009

Возможно ли в C # создать System.Collections.Generic.Dictionary<TKey, TValue>, где TKey - это безусловный класс, а TValue - анонимный класс с рядом свойств, например - имя столбца базы данных и его локализованное имя.

Примерно так:

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

Ответы [ 4 ]

41 голосов
/ 25 октября 2009

Вы не можете объявить такой тип словаря напрямую (есть kludges, но они предназначены только для развлечений и новизны), но если ваши данные поступают из источника IEnumerable или IQueryable, вы можете получить их с помощью оператора LINQ ToDictionary и проецирование требуемого ключа и (анонимно набранного) значения из элементов последовательности:

var intToAnon = sourceSequence.ToDictionary(
    e => e.Id,
    e => new { e.Column, e.Localized });
18 голосов
/ 25 октября 2009

Как сказал itowlson , вы не можете объявить такого зверя, но вы действительно можете создать один:

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 = "Доллар" });
}

Непонятно, почему вы на самом деле хотите использовать код, подобный этому.

4 голосов
/ 04 февраля 2012

Я думаю, что ASP.NET MVC не завершился, когда был задан этот вопрос. Он конвертирует анонимные объекты в словари внутри.

Взгляните, например, на HtmlHelper класс . Метод, который переводит объекты в словари: AnonymousObjectToHtmlAttributes. Это специфицировано в MVC и возвращает RouteValueDictionary, однако.

Если вы хотите что-то более общее, попробуйте это:

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

Одним из интересных моментов этой реализации является то, что она возвращает пустой словарь для null объектов.

А вот одна общая версия:

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))
        );
}
3 голосов
/ 19 августа 2010

Вы можете сделать перефразирование

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