A dictionary where value is an anonymous type in C#
-
06-07-2019 - |
Question
Is it possible in C# to create a System.Collections.Generic.Dictionary<TKey, TValue>
where TKey
is unconditioned class and TValue
- an anonymous class with a number of properties, for example - database column name and it's localized name.
Something like this:
new { ID = 1, Name = new { Column = "Dollar", Localized = "Доллар" } }
Solution
You can't declare such a dictionary type directly (there are kludges but these are for entertainment and novelty purposes only), but if your data is coming from an IEnumerable or IQueryable source, you can get one using the LINQ ToDictionary operator and projecting out the required key and (anonymously typed) value from the sequence elements:
var intToAnon = sourceSequence.ToDictionary(
e => e.Id,
e => new { e.Column, e.Localized });
OTHER TIPS
As itowlson said, you can't declare such a beast, but you can indeed create one:
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 = "Доллар" });
}
It's not clear why you'd actually want to use code like this.
I think ASP.NET MVC didn't exit at the time this question was made. It does convert anonymous objects to dictionaries internally.
Just take a look at the HtmlHelper
class, for example. The method that translates objects to dictionaries is the AnonymousObjectToHtmlAttributes
. It it's specifc to MVC and returns an RouteValueDictionary
, however.
If you want something more generic, try this:
public static IDictionary<string,object> AnonymousObjectToDictionary(object obj)
{
return TypeDescriptor.GetProperties(obj)
.OfType<PropertyDescriptor>()
.ToDictionary(
prop => prop.Name,
prop => prop.GetValue(obj)
);
}
One intersting advatages of this implementation is that it returns an empty dictionary for null
objects.
And here's one generic version:
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))
);
}
You can do a refection
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;
}
}