2013-08-17 28 views
5

Dowiedziałem się trochę o odbiciach w języku C# i chciałbym wiedzieć, czy używam słownika z kluczami-wartościami, czy mogę utworzyć obiekt ze zmienną o nazwie każdego klucza w słowniku i ich wartości, kluczowej wartości tego słownika.Generowanie obiektu dynamicznego ze słownika za pomocą C# Reflection

Mam metodę, która działa odwrotnie, wyodrębnia obiekt ze słownika, ten słownik zawiera klucze i właściwości klasy oraz ich wartości, wartość właściwości.

Zastanawiam się, jak to zrobić, jeśli to możliwe.

Poniżej jest moja metoda, która wydobywa słownika obiektu:

protected Dictionary<String, String> getObjectProperty(object objeto) 
{ 
    Dictionary<String, String> dictionary = new Dictionary<String, String>(); 

    Type type = objeto.GetType(); 
    FieldInfo[] field = type.GetFields(); 
    PropertyInfo[] myPropertyInfo = type.GetProperties(); 

    String value = null; 

    foreach (var propertyInfo in myPropertyInfo) 
    { 
     if (propertyInfo.GetIndexParameters().Length == 0) 
     { 
      value = (string)propertyInfo.GetValue(objeto, null); 
      value = value == null ? null : value; 
      dictionary.Add(propertyInfo.Name.ToString(), value); 
     } 
    } 

    return dictionary; 
} 
+2

Czy masz na myśli 'dynamiczny' wpisany obiekt? Lub utworzyć nowy typ? – Euphoric

+0

Jakiej wersji platformy .NET używasz? –

+0

Obiekt już istnieje, po wyjściu z tej funkcji, po prostu muszę rzucić (myObject) wynik z tego do istniejącego obiektu. .NET 4.0 –

Odpowiedz

2

nie jestem pewien, czy to jest to, czego szukasz, ale sądząc po swoje pytanie, myślę, że chcesz tworzyć typy w czasie wykonywania z typów znajdujących się w słowniku, które będą uzyskiwane przez podanie klucza.

Jeśli tak, to możesz utworzyć następującą klasę, która będzie zawierać pary klucz-wartość łańcuchów, które będą Twoimi kluczami, oraz Typy, które będą reprezentować twoje wartości, które będą tworzone.

class DictionaryActivator 
{ 
    Dictionary<string, Type> Dictionary = new Dictionary<string, Type>(); 

    public DictionaryActivator() 
    { 
     Dictionary.Add("MyCar", typeof(Car)); 
     Dictionary.Add("MyHouse", typeof(House)); 
     Dictionary.Add("MyFruit", typeof(Fruit)); 
     Dictionary.Add("MyComputer", typeof(Computer)); 
    } 

    public T GetInstance<T>(string type, params object[] parameters) 
    { 
     if (parameters.Count() == 0) 
     { 
      return (T)Activator.CreateInstance(Dictionary[type]); 
     } 
     else 
     { 
      return (T)Activator.CreateInstance(Dictionary[type], parameters.ToArray()); 
     } 
    } 
} 

Można również utworzyć cztery klasy testów, aby przetestować tę konfigurację.

class House 
{ 
    public int Number = 25; 
} 

class Car 
{ 
    public double Price = 50000; 
} 

class Fruit 
{ 
    public string Name = "Apple"; 
} 

class Computer 
{ 
    public string Cpu { get; set; } 
    public string Gpu { get; set; } 

    public Computer(string cpu, string gpu) 
    { 
     Cpu = cpu; 
     Gpu = gpu; 
    } 
} 

Gdy to nastąpi, można uruchomić następujące linie kodu, aby uzyskać wszystkie typy ze słownika, instancję je i wrzucił je do odpowiednich typów. Jak można zauważyć, ostatni przykład pokazuje, jak dodać wiele parametrów (w tym przypadku dwa) do nowo utworzonej instancji i zwrócić ją jako instancję obiektu obiekt.

Na koniec można go rzucić na typ Komputer, aby można było sprawdzić, czy parametry konstruktora rzeczywiście trafiły do ​​odpowiednich właściwości.

class Program 
{ 
    static void Main() 
    { 
     var source = new DictionaryActivator(); 

     Console.WriteLine(source.GetInstance<Car>("MyCar").Price); 
     Console.WriteLine(source.GetInstance<House>("MyHouse").Number); 
     Console.WriteLine(source.GetInstance<Fruit>("MyFruit").Name); 

     var computer = source.GetInstance<object>("MyComputer", "Fast CPU", "Fast GPU"); 

     Console.WriteLine((computer as Computer).Cpu); 
     Console.WriteLine((computer as Computer).Gpu); 

     Console.Read(); 
    } 
} 
+0

można utworzyć obiekt typu obiektu i dodać na przykład dwa zmienne do niego z ich wartościami i zwracają je? –

+0

Edytowałem swoją odpowiedź, więc tak, możesz zrobić dokładnie to. Wystarczy przekazać tyle parametrów do nowej instancji i przesłać je do obiektu, używając ogólnego typu zdefiniowanego w metodzie GetInstance (string, params object []). –

11

Jeśli już masz słownika, chciałbym uniknąć refleksji i po prostu użyć DynamicObject

na przykład:

public class DynamicDictionary : DynamicObject 
{ 
    private readonly Dictionary<string, object> dictionary; 

    public DynamicDictionary(Dictionary<string, object> dictionary) 
    { 
     this.dictionary = dictionary; 
    } 

    public override bool TryGetMember(
     GetMemberBinder binder, out object result) 
    { 
     return dictionary.TryGetValue(binder.Name, out result); 
    } 

    public override bool TrySetMember(
     SetMemberBinder binder, object value) 
    { 
     dictionary[binder.Name] = value; 

     return true; 
    } 
} 

które mogą być wykorzystane w następujący sposób:

dynamic x = new DynamicDictionary(
    new Dictionary<string, object> {{"Name", "Peter"}}); 

Console.WriteLine(x.Name); 
1

Ponieważ ExpandoObject jest słownikiem, możesz użyć tej funkcji rozszerzenia:

public static object With(this IDictionary<string, object> obj, IDictionary<string,object> additionalProperties) 
{ 
    foreach (var name in additionalProperties.Keys) 
    obj[name] = additionalProperties[name]; 
    return obj; 
} 

Zastosowanie:

var dynamicObj = new System.Dynamic.ExpandoObject().With(myDictionary);