C#でSystem.Collections.Generic.Dictionary<TKey, TValue>
を作成することはできますか。ここで、TKey
は無条件のクラスであり、TValue
-多くのプロパティを持つ匿名クラスです。たとえば、データベースの列名とローカライズされた名前です。 。
このようなもの:
new { ID = 1, Name = new { Column = "Dollar", Localized = "Доллар" } }
そのようなディクショナリタイプを直接宣言することはできません(kludgeはありますが、これらは娯楽と目新しさの目的のみです)。ただし、データがIEnumerable
またはIQueryable
ソースからのものである場合、 LINQ ToDictionary()
演算子を使用して取得し、シーケンス要素から必要なキーと(匿名で入力された)値を投影します。
var intToAnon = sourceSequence.ToDictionary(
e => e.Id,
e => new { e.Column, e.Localized });
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コードを実際に使用する理由が明確ではありません。
この質問がなされたとき、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))
);
}
あなたは反射を行うことができます
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;
}
}
空の辞書を初期化したい場合は、次のようにします。
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});