views:

896

answers:

3

Is it possible in C# 3.net 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 = "Доллар" } }
+8  A: 

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 });
itowlson
thanks! I will use your code. Before it I do next: var q = from row in table.AsEnumerable() select ..
abatishchev
+4  A: 

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.

Dan
Why? I can think of a number of reasons. Here's one. Consider for example a dictionary used to memoize an n-ary function, say a function of four int arguments. In the next version of the CLR of course you'd just use a 4-tuple, but in C# 3, you could create a dictionary of anonymous type {int, int, int, int}, done, no need to define your own tuple type.
Eric Lippert
I now have another entry for the "brushes with fame" section of my personal homepage! :-)
Dan
+1  A: 

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;
    }
}
noneno
Good idea. Also you can make it generic: `public static IDictionary<string, T> ToDictionary(this object data) { }`
abatishchev