web-dev-qa-db-ja.com

値がC#の匿名型である辞書

C#でSystem.Collections.Generic.Dictionary<TKey, TValue>を作成することはできますか。ここで、TKeyは無条件のクラスであり、TValue-多くのプロパティを持つ匿名クラスです。たとえば、データベースの列名とローカライズされた名前です。 。

このようなもの:

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

そのようなディクショナリタイプを直接宣言することはできません(kludgeはありますが、これらは娯楽と目新しさの目的のみです)。ただし、データがIEnumerableまたはIQueryableソースからのものである場合、 LINQ ToDictionary()演算子を使用して取得し、シーケンス要素から必要なキーと(匿名で入力された)値を投影します。

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

itowlsonsaid のように、そのような獣をdeclareすることはできませんが、確かにcreate1つ:

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

このようなuseコードを実際に使用する理由が明確ではありません。

18
Ðаn

この質問がなされたとき、ASP.NET MVCは終了しなかったと思います。匿名オブジェクトを内部的に辞書に変換します。

たとえば HtmlHelper class を見てください。オブジェクトを辞書に変換するメソッドは 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)
        );
}

この実装の興味深い利点の1つは、nullオブジェクトの空の辞書を返すことです。

そして、ここに1つの一般的なバージョンがあります:

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))
        );
}
4
jpbochi

あなたは反射を行うことができます

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;
    }
}
3
noneno

空の辞書を初期化したい場合は、次のようにします。

var emptyDict = Enumerable
    .Empty<(int, string)>()
    .ToDictionary(
         x => new { Id = x.Item1 }, 
         x => new { Column = x.Item2, Localized = x.Item2});

基本的には、最終的な匿名型で使用したい型を持つタプルを持つ空の列挙型が必要であり、その後、好きな方法で入力された空の辞書を取得できます。

タプルのタイプにも名前を付けることができます:

var emptyDict = Enumerable
            .Empty<(int anInt, string aString)>()
            .ToDictionary(
                x => new { Id = x.anInt },
                x => new { Column = x.aString, Localized = x.aString});
0
Kevek