2017-08-18 3 views
4

Lassen Sie mich zum besseren Verständnis der FrageIst es möglich, Werttyp basierend auf dem Schlüssel auf Schlüssel/Wert-Paar in C# zu haben?

Bibliothek hält ein einfaches Beispiel:

enum Keys 
{ 
    [Description("Color select")] 
    ColorSelection, 

    [Description("Day select")] 
    DaySelection, 

    [Description("Gender select")] 
    GenderSelection 
} 


enum Color 
{ 
    [Description("White color")] 
    White, 

    [Description("Black color")] 
    Black, 

    [Description("Brown color")] 
    Brown 
} 
enum Day 
{ 
    [Description("Monday")] 
    Monday, 

    [Description("Tueday")] 
    Tuesday, 

    [Description("Wednesday")] 
    Wednesday 
} 

enum Gender 
{ 
    [Description("Male gender")] 
    Male, 

    [Description("Female gender")] 
    Female    
} 

From Client ich so wollen:

Dictionary<Keys, ??> values = new Dictionary<Keys, ??>(); 

values.Add(Keys.ColorSelection, <Auto suggest color>); 
values.Add(Keys.DaySelection, <Auto suggest day>); 

Ich bin okay, Ändern Sie die Bibliothek, um eine Liste von values als Enum zu haben, aber ich möchte, dass der Client automatisch die Werte wi vorschlägt Die Filter basieren auf dem Schlüssel.

Hinweis:
1. Ich möchte nicht Klasse (Modell) mit der Eigenschaft als jeweilige Art, da es viele Schlüssel in der Bibliothek und Client sind holen wenige und Werte zu liefern.
2. I-Werte nicht allein als List<Values> haben kann, da einige Fälle gleiche description als Wert mit verschiedenen Schlüsseln .. Eg haben:

Anregungen „Ja/Nein-Werte werden mit verschiedenen Schlüsseln gleich sein“? Vielen Dank im Voraus ..

+1

Ich verstehe Ihre Frage nicht ... warum wollen Sie nicht eine Klasse verwenden? Viele Schlüssel zu haben hält dich nicht davon ab, Klassen zu benutzen ... Du meinst ein Struct? – Milney

+0

@Milney Say habe ich 'Klasse' namens' Detail' mit 200 Eigenschaften und von Client Ich werde 3 Eigenschaften mit Wert (zB: Schlüssel, Farbe Geschlecht) und Ruhe (197) wird 'null'. Ich glaube nicht, dass es der richtige Weg ist. – Gopichandar

+5

Ich würde ernsthaft Ihr Design überdenken ... 'Werttypen' wird Ihnen nicht helfen, dieses Problem zu vermeiden ... Sie können ein Wörterbuch haben, mit 3 Schlüsseln hinzugefügt - die Werte für diese 3 Schlüssel sind Ihre Detailklasse .. keine Nullen beteiligt – Milney

Antwort

0

Sie Ihren Wörterbuch erklären könnte wie:

var dictionary = new Dictionary<Keys, int>(); 

Und dann kapseln diese in Ihrer eigenen benutzerdefinierten Klasse mit einer Methode, die den Schlüssel Wert des Schlüssels verwendet den Wert zu interpretieren mit dem entsprechenden enum.

Das ganze Problem scheint hier jedoch wie ein Code-Geruch.

0

Ich stimme @ @ owen-pauling zu; Ich denke, du solltest dein aktuelles Design überarbeiten. Aber am Beispiel Ihnen präsentiert, hier ist ein Weg, dies zu Dictionary<Keys, int> mit umgehen kann:

Dictionary<Keys, int> values = new Dictionary<Keys, int>(); 
values.Add(Keys.ColorSelection, Convert.ToInt32(Color.Black)); 
values.Add(Keys.GenderSelection, Convert.ToInt32(Gender.Male)); 
values.Add(Keys.DaySelection, Convert.ToInt32(Day.Wednesday)); 

foreach (KeyValuePair<Keys, int> kv in values) 
{ 
    dynamic enumValue = null; 

    switch (kv.Key) 
    { 
     case Keys.ColorSelection: 
      enumValue = Enum.Parse(typeof(Color), Convert.ToString(kv.Value)); 
      break; 

     case Keys.DaySelection: 
      enumValue = Enum.Parse(typeof(Day), Convert.ToString(kv.Value)); 
      break; 

     case Keys.GenderSelection: 
      enumValue = Enum.Parse(typeof(Gender), Convert.ToString(kv.Value)); 
      break; 
    } 

    Console.WriteLine(String.Format("Enum value: {0}", enumValue)); 
} 

/* Output: 
Enum value: Black 
Enum value: Male 
Enum value: Wednesday 
*/ 

Wenn Sie die Änderungen offen sind, vielleicht eine Klasse, um die Auswahl von dem Client zu halten genügt. Hier ist ein Beispiel mit List<DetailSelection>:

public class DetailSelection 
{ 
    public DetailSelection() { } 

    public Type SelectionType { get; set; } 
    public string Description { get; set; } 
    public int EnumValue { get; set; } 
} 

List<DetailSelection> details = new List<DetailSelection>(); 
details.Add(new DetailSelection() { 
    Description = "Color description", 
    SelectionType = typeof(Color), 
    EnumValue = Convert.ToInt32(Color.Black) 
}); 
details.Add(new DetailSelection() { 
    Description = "Day description", 
    SelectionType = typeof(Day), 
    EnumValue = Convert.ToInt32(Day.Wednesday) 
}); 
details.Add(new DetailSelection() { 
    Description = "Gender description", 
    SelectionType = typeof(Gender), 
    EnumValue = Convert.ToInt32(Gender.Male) 
}); 

foreach (var detail in details) 
{ 
    var enumValue = Enum.Parse(detail.SelectionType, Convert.ToString(detail.EnumValue)); 

    Console.WriteLine(String.Format("Enum value: {0}", enumValue)); 
} 

/* Output: 
Enum value: Black 
Enum value: Wednesday 
Enum value: Male 
*/ 

In jedem Fall würde ich wahrscheinlich versuchen, einen Schritt zurück zu nehmen und neu zu bewerten Ihr Design; nur ein freundlicher Ratschlag. :-)

Ich glaube nicht, dass Sie eine Dictionary<TKey, TValue> dafür verwenden sollten; Da der Schlüssel eindeutig sein muss, werden Sie den Client auf nur eine einzige ColorSelection, GenderSelection, DaySelection usw. beschränken.

0

Ich denke, die einfachste (und wahrscheinlich beste) Lösung ist, was Milney in einem Kommentar vorgeschlagen:

class Properties 
{ 
    Color? ColorSelection { get; set; } 
    Day? DaySelection { get; set; } 
    Gender? GenderSelection { get; set; } 
} 

Client-Code:

Properties values = new Properties(); 

values.ColorSelection = < Auto suggest color >; 
values.DaySelection = < Auto suggest day >; 

Allerdings scheinen Sie besorgt über Hunderte von Eigenschaften aufweist, wo nur wenige von ihnen Werte haben würde.Dies ist wahrscheinlich eine Frage von vorzeitige Optimierung: Es fühlt sich verschwenderisch, aber Entwickler Zeit ist um Größenordnungen mehr wert als alle Speicherressourcen, die dieser Ansatz kosten könnte. Wenn jedoch die wirklich stört, oder wenn Sie durch Belastungstests feststellen, dass dies tatsächlich ein Problem ist, können Sie Ihre Implementierungen optimieren, ohne eine Änderung der Klienten Code erforderlich:

class Properties 
{ 
    private Dictionary<Type, int> values = new Dictionary<Type, int>(); 
    Color? ColorSelection 
    { 
     get 
     { 
      return values.TryGetValue(typeof(Color), out int i) 
       ? (Color?)i 
       : null; 
     } 
     set 
     { 
      values[typeof(Color)] = (int)value; 
     } 
    } 
    ... 
} 

Dies läßt Ihre API genau die gleichen , speichert jedoch alle Werte in einem Wörterbuch, so wie Sie es angefordert haben. Sie können auch Type für Ihre Keys enum ersetzen, wenn Sie bevorzugen. Tatsächlich könnten Sie eine universelle "Add" -Methode für Ihre Klasse Properties erstellen, wenn Sie zulassen möchten, dass Client-Code programmgesteuert Werte basierend auf zur Laufzeit bekannten Daten hinzufügt. Wenn Kunden jedoch IntelliSense-Vorschläge wünschen, können sie stattdessen die Eigenschaften verwenden.

Wenn Sie diese Route gehen, würde ich vorschlagen, eine T4-Vorlage zu verwenden, um Ihre Eigenschaftenklasse zu generieren, so dass Sie nicht große Mengen von Vorlagendefinitionen schreiben.

Verwandte Themen