Словарь, в котором значение является анонимным типом в С#
Возможно ли в С# создать System.Collections.Generic.Dictionary<TKey, TValue>
, где TKey
- безусловный класс, а TValue
- анонимный класс с рядом свойств, например - имя столбца базы данных и его локализованное имя.
Что-то вроде этого:
new { ID = 1, Name = new { Column = "Dollar", Localized = "Доллар" } }
Ответы
Ответ 1
Вы не можете объявить такой тип словаря напрямую (есть клоды, но они предназначены только для развлечений и новинок), но если ваши данные поступают из источника IEnumerable или IQueryable, вы можете получить его с помощью оператора LINQ ToDictionary и проецирования требуемого ключа и (анонимно типизированного) значения из элементов последовательности:
var intToAnon = sourceSequence.ToDictionary(
e => e.Id,
e => new { e.Column, e.Localized });
Ответ 2
Как 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 = "Доллар" });
}
Не понятно, почему вы действительно хотите использовать такой код.
Ответ 3
Вы можете сделать исправление
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;
}
}
Ответ 4
Я думаю, что 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))
);
}