2010-11-05 3 views
3

У меня есть List<CustomObject> который имеет 3 свойства A, B, C и то, что мне нужно, чтобы преобразовать этот список в словарь, так что результат выглядитСписок <T> к словарю

Dictionary<string,object> 
(Property name) A = Value of A 
(Property name) B = Value of B 
(Property name) C = Value of C 

Pls предложить ...

+0

Я бы сделал его «Словарь <строка, объект>'. – leppie

+0

да нет проблем с этим ... Я ищу sloution – chugh97

+0

IIRC Я разместил решение (используя Reflection.Emit) для этого в другом вопросе. Это было давно, и я не могу вспомнить ссылку сейчас. Будет ли сообщение, если найду его. – leppie

ответ

5
CustomObject instance = new CustomObject(); 
var dict = instance.GetType().GetProperties() 
    .ToDictionary(p => p.Name, p => p.GetValue(instance, null)); 
+0

Вам нужно 'instance.GetType()', чтобы заставить его работать любой тип, еще довольно приятный «один лайнер» :) – leppie

+0

@leppie - Да, это лучший способ сделать это, спасибо. – Lee

0

Если я правильно понимаю, что вы хотите сделать, вы должны использовать reflrecion на CustomObject, чтобы получить имена свойств, то просто создать словарь:

dic.add (propertyName, value);

+0

Очень скучно и очень медленно :) – leppie

2

Я нашел код :) Первоначально от here.

static T CreateDelegate<T>(this DynamicMethod dm) where T : class 
{ 
    return dm.CreateDelegate(typeof(T)) as T; 
} 

static Dictionary<Type, Func<object, Dictionary<string, object>>> cache = 
    new Dictionary<Type, Func<object, Dictionary<string, object>>>(); 

static Dictionary<string, object> GetProperties(object o) 
{ 
    var t = o.GetType(); 

    Func<object, Dictionary<string, object>> getter; 

    if (!cache.TryGetValue(t, out getter)) 
    { 
    var rettype = typeof(Dictionary<string, object>); 

    var dm = new DynamicMethod(t.Name + ":GetProperties", rettype, 
     new Type[] { typeof(object) }, t); 

    var ilgen = dm.GetILGenerator(); 

    var instance = ilgen.DeclareLocal(t); 
    var dict = ilgen.DeclareLocal(rettype); 

    ilgen.Emit(OpCodes.Ldarg_0); 
    ilgen.Emit(OpCodes.Castclass, t); 
    ilgen.Emit(OpCodes.Stloc, instance); 

    ilgen.Emit(OpCodes.Newobj, rettype.GetConstructor(Type.EmptyTypes)); 
    ilgen.Emit(OpCodes.Stloc, dict); 

    var add = rettype.GetMethod("Add"); 

    foreach (var prop in t.GetProperties(
     BindingFlags.Instance | 
     BindingFlags.Public)) 
    { 
     ilgen.Emit(OpCodes.Ldloc, dict); 

     ilgen.Emit(OpCodes.Ldstr, prop.Name); 

     ilgen.Emit(OpCodes.Ldloc, instance); 
     ilgen.Emit(OpCodes.Ldfld, prop); 
     ilgen.Emit(OpCodes.Castclass, typeof(object)); 

     ilgen.Emit(OpCodes.Callvirt, add); 
    } 

    ilgen.Emit(OpCodes.Ldloc, dict); 
    ilgen.Emit(OpCodes.Ret); 

    cache[t] = getter = 
     dm.CreateDelegate<Func<object, Dictionary<string, object>>>(); 
    } 

    return getter(o); 
} 

Для данного типа:

class Foo 
{ 
    public string A {get;} 
    public int B {get;} 
    public bool C {get;} 
} 

Он производит делегат эквивалент:

(Foo f) => new Dictionary<string, object> 
    { 
    { "A", f.A }, 
    { "B", f.B }, 
    { "C", f.C }, 
    }; 

Отказ от ответственности: Глядя на код сейчас (без тестирования) там, возможно, потребуется специальная обработка для ценностей (а не только класс). Упражнение для читателя.

+0

интересно. мне это нравится. – Hath

+0

@Hath: Я был «вынужден» написать его для системы перевода/глобализации, которая должна была быстро отражать элементы управления WinForm. :) – leppie

+0

awesome! Я только начинал кодировать его таким образом, но вам удалось сделать это быстрее:) Это определенно самый быстрый способ сделать это :) Хотя, вероятно, не такой элегантный, как LINQ one :) – luckyluke

Смежные вопросы