2016-09-29 2 views
3

Ich habe ein Objekt-Array von Key-Werten.Map Object [] mit Key Value-Eigenschaften zu den Eigenschaften eines Objekts, ohne einen riesigen, fiesen Schalter zu verwenden

public class KeyValueStore 
{ 
    public string Key {get;set;} 
    public string Value {get;set;} 
} 

Dieses Array speichert die Werte eines Objekts i so zu füllen versuche:

public class Customer 
{ 
    public string Name {get;set;} 
    public string Country {get;set} 
} 

Deshalb möchte ich diese Schlüssel von KeyValueStore zu Kunden Eigenschaften abzubilden

public Customer TransformToCustomer(KeyValueStore[] keyValueStore) 
{ 
    var customer = new Customer(); 

    foreach (var keyValue in keyValueStore) 
    { 
     switch (keyValue.Key) 
     { 
      case "Name": 
       customer.Name = keyValue.Value; 
       break; 
      case "Cntry": 
       customer.Country = keyValue.Value; 
       break; 
     } 
    } 

    return customer; 
} 

Ist gibt es einen besseren Weg, dies zu tun?

+0

Aus einem schnellen Blick wird es schwierig sein, jede Art von Code zu vermeiden, da Ihre Keys kein Ereignis sind, das sich an die Eigenschaften anpasst. Was ich meine, ist "" Cntry "! = Land" –

+0

Angenommen, dass Schlüssel sind eigentlich Namen, ohne Tippfehler, werfen Sie einen Blick hier: http://StackOverflow.com/Questions/7718792/Can-i-Set-A-Property -value-with-reflection – kiziu

+1

Gibt es einen Grund, warum Sie das 'Dictionary' hier mit Ihrer' KeyValueStore' Klasse neu erfinden? –

Antwort

2

Ja, unter der Annahme, dass der Zieltyp einen parameterlosen Konstruktor hat, könnten Sie eine generische Methode schreiben, tut dies:

public T CreateAndPopulate<T>(IEnumerable<KeyValueStore> propStore, 
           IDictionary<string, string> mapping = null) 
          where T:class,new() 
{ 

    T item=new T(); 
    var type=typeof(T); 
    foreach(var kvs in propStore) 
    { 
     var propName = kvs.Key; 
     propName = mapping !=null && mapping.ContainsKey(propName) 
         ? mapping[propName] 
         : propName; 
     var prop = type.GetProperty(propName); 
     if(prop == null) //does the property exist? 
     { 
      continue; 
     } 
     var propMethodInfo = prop.GetSetMethod(); 
     if(propMethodInfo == null) //does it have a set method? 
     { 
      continue; 
     } 
     propMethodInfo.Invoke(item, new[]{ kvs.Value }); 
    } 
    return item; 
} 

und verwenden es:

IEnumerable<KeyValueStore> propStore = new KeyValueStore[]{ 
    new KeyValueStore{ Key = "Name", Value = "John" }, 
    new KeyValueStore{ Key = "Cntry", Value = "UK" }}; 
var mapping = new Dictionary<string,string>{{ "Cntry", "Country" }}; 

var customer = CreateAndPopulate<Customer>(propStore, mapping); 
+0

Das hat super funktioniert! Vielen Dank. – PolkaHard

1

Ich habe einen anderen Vorschlag, ein Viele Male große Schalter Blöcke zeigt an, dass Sie etwas mit Ihren Objekten desigen fehlen, und richtige Verwendung von Polymorphie kann die Switch-Nutzung ersetzen.

Zuerst werden wir die KeyValueStore Klasse Redesign ValueStore Klassen seprate, die jeder die gemeinsame Schnittstelle IValueStore implementieren, wird die Schnittstelle wie folgen aussehen:

public interface IValueStore 
{ 
    void AddValueToCostumer(Customer customer); 
} 

Jetzt NameValueStor werden wie folgt aussehen:

public class NameValueStore : IValueStore 
{ 
    private readonly string _name;  

    public NameValueStore(string name) 
    { 
     _name = name; 
    } 

    public void AddValueToCustomer(Costumer costumer) 
    { 
     customer.Name = _name; 
    } 
} 

Und CountryValueStor:

public class CountryValueStore : IValueStore 
{ 
    private readonly string _country;  

    public CountryNameValueStore(string country) 
    { 
     _country = country; 
    } 

    public void AddValueToCustomer(Costumer costumer) 
    { 
     customer.Country = _country; 
    } 
} 

Und nun Ihre Funktion TransformToCustomer könnte wie folgt aussehen:

public Customer TransformToCustomer(IValueStore[] valueStores) 
{ 
    var customer = new Customer(); 

    foreach (var valueStore in valueStores) 
    { 
     valueStore.AddValueToCustomer(customer); 
    } 

    return customer; 
} 

Diese Lösung fühlt sich viel mehr SOLID mir.

Hoffe es hilft!

+0

Das ist keine Option für mich. Meine Kundenklasse ist eigentlich sehr groß. Ich muss 50 Klassen für alle Eigenschaften machen. Aber das könnte wirklich die Lösung für kleinere Klassen sein. Vielen Dank für Ihre Hilfe! :) – PolkaHard

+0

Ich stimme zu, dass in diesem Fall 50 Klassen zu diesem Zweck nicht wert sind, aber in Fällen, in denen jede der Logik-Klassen komplexer ist als Ihre, ist es manchmal den Overhead der Erstellung einer Menge kleiner Klassen wert Macht des Polymorphismus. – YuvShap

+0

Und ich stimme dem auch zu. :) Diese Antwort war sehr hilfreich für zukünftige Projekte! – PolkaHard

Verwandte Themen