2011-01-04 6 views
1

Dies könnte eine einfache sein, aber mein Kopf weigert sich, um diese zu wickeln, so dass eine Außenansicht in diesem Fall immer nützlich ist!C# -Klasse Design mit generischer Struktur

Ich muss eine Objekthierarchie entwerfen, um eine Parameterregistrierung für einen Patienten zu implementieren. Dies wird zu einem bestimmten Zeitpunkt stattfinden und eine Anzahl verschiedener Parameter über einen Patienten sammeln (Blutdruck, Herzfrequenz usw.). Die Werte dieser Parameterregistrierungen können unterschiedlicher Art sein, z. B. Strings, Integer, Floats oder sogar Guids (für Lookup-Listen).

So haben wir:

public class ParameterRegistration 
{ 
    public DateTime RegistrationDate { get; set; } 
    public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; } 
} 

public class ParameterRegistrationValue 
{ 
    public Parameter Parameter { get; set; } 
    public RegistrationValue RegistrationValue { get; set; } // this needs to accomodate the different possible types of registrations! 
} 


public class Parameter 
    { 
    // some general information about Parameters 
    } 

public class RegistrationValue<T> 
{ 
    public RegistrationValue(T value) 
    { 
    Value = value; 
    } 

    public T Value { get; private set; } 
} 

UPDATE: Dank der Anregungen, hat sich das Modell gemorpht nun folgendes:

public class ParameterRegistration 
{ 
    public DateTime RegistrationDate { get; set; } 
    public IList<ParameterRegistrationValue> ParameterRegistrationValues { get; set; } 
} 

public abstract class ParameterRegistrationValue() 
{ 
    public static ParameterRegistrationValue CreateParameterRegistrationValue(ParameterType type) 
{ 
    switch(type) 
    { 
     case ParameterType.Integer: 
      return new ParameterRegistrationValue<Int32>(); 
     case ParameterType.String: 
       return new ParameterRegistrationValue<String>(); 
     case ParameterType.Guid: 
      return new ParameterRegistrationValue<Guid>(); 
     default: throw new ArgumentOutOfRangeException("Invalid ParameterType: " + type); 
    } 
} 
    public Parameter Parameter { get; set; } 
} 

public class ParameterRegistrationValue<T> : ParameterRegistrationValue 
{ 
    public T RegistrationValue {get; set; } 
} 

public enum ParameterType 
{ 
    Integer, 
    Guid, 
    String 
} 

public class Parameter 
{ 
    public string ParameterName { get; set; } 
    public ParameterType ParameterType { get; set;} 
} 

die in der Tat ein bisschen einfacher, aber jetzt frage ich mich, da die IList in ParameterRegistration auf die abstrakte ParameterRegistrationValue Objekt, wie werde ich in der Lage, th zu bekommen e Istwert out (da es auf den Unterobjekten gespeichert ist)?

Vielleicht ist die ganze allgemeine Sache ist in der Tat nicht ganz die Art und Weise, nachdem alle zu gehen: s

+0

Und was ist die Frage und warum verwenden Sie öffentliche Fieds? –

+0

Sie haben nicht erwähnt, was Ihr Problem ist. –

+0

Was * fehlt * du hier? Funktioniert das nicht? Wo/wie scheitert es? –

Antwort

4

Wenn Sie dies nicht tun kennen den endgültigen Parametersatz und den entsprechenden Typ jedes Parameters, dann werden die Generika wahrscheinlich nicht helfen - verwenden Sie Objekt als Parameter Werttyp.

Darüber hinaus wird das Durchlaufen der Parameterliste mühsam sein, da Sie den Typ jedes Elements untersuchen müssen, um zu bestimmen, wie der Wert behandelt wird.

Was versuchen Sie mit Generika zu erreichen?Ja, sie sind cool (und Boxen/Unboxing ist wahrscheinlich keine gute Idee), aber in einigen Fällen möchten Sie vielleicht Objekt stattdessen verwenden (für Einfachheit und Flexibilität).

- Pavel

+0

kenne ich Typ von jedem Parameter, diese Information wird in der Datenbank gespeichert und steht somit zum Abruf bereit. – Sam

+0

Okay, in diesem Fall würde ich vorschlagen, einen nicht-generischen Typ als Sammlungsart (eine Liste von Parametern) und das Factory-Muster zu verwenden, um den spezifischen Parameterwerttyp basierend auf dem tatsächlichen Parameterwert abzurufen. Aber es lohnt sich immer noch nicht, Generika hier zu verwenden, imho. – volpav

+0

Je mehr ich damit bastele, desto mehr fange ich an, Ihnen zuzustimmen, Generika sind auch nicht gerade ideal. Würdest du zufällig ein Beispiel für die Struktur haben, die du für diese Aufgabe implementieren würdest? Vielen Dank! – Sam

0

sein kann, sollten Sie den öffentlichen RegistrationValue RegistrationValue verwenden, wobei T - Typ ist, in generic verwenden. Zum Beispiel ist T - String oder eine andere Klasse oder Struktur.

Oder Sie sollten die Klasse ParameterRegistrationValue als generisch definieren, um generisches Argument im Feld RegistrationValue zu verwenden.

2

Was Sie einführen möchten, ist eine abstrakte Basisklasse für RegistrationValue<T>, die nicht generisch ist, so dass Ihre ParameterRegistrationValue Klasse eine nicht-generische Referenz enthalten kann, ohne dass Sie den Typ benötigen. . Alternativ kann es sinnvoll sein, auch ParameterRegistrationValue Generika zu machen, und dann eine nicht-generische Basisklasse für sich stattdessen hinzufügen (so dass die Liste der Werte in ParameterRegistration unterschiedlichen Art sein kann

1. Weg:

public abstract class RegistrationValue 
{ 
} 

public class RegistrationValue<T> : RegistrationValue 
{ 
    public RegistrationValue(T value) 
    { 
    Value = value; 
    } 

    public T Value { get; private set; } 
} 
kompilieren

Und jetzt sollten Sie Ihren Code.


Sobald Sie eine nicht-generische Basisklasse haben, habe ich auch keine Mitglieder der allgemeinen Klasse bewegen würde, die in nicht bis auf die generischen Typparametern abhängen Diese Basisklasse Es gibt keine in th Beispiel hierfür ist, aber wenn wir stattdessen ParameterRegistrationValue modifiziert wurden generisch zu sein, würde ich Parameter bis in die nicht-generische Basisklasse bewegen (weil es nicht für RegistrationValue vom Typ Parameter abhängt)

+0

Sie müssten definitiv von verschiedenen Typen sein, da eine Parameterregistrierung viele verschiedene Arten von Registrierungen enthalten kann. – Sam

+0

Damien, wenn du sagst "make ParmaterRegistrationValue generic", meinst du statt RegistrationValue oder zusätzlich dazu? – Sam

+0

@Sam - Ich dachte darüber hinaus - auf diese Weise könnte die Eigenschaft "RegistrationValue" von einem bestimmten Typ sein. Es hängt davon ab, wie hoch die Hierarchie ist, um die generischen Informationen beizubehalten, und auf welcher Ebene wir sie definitiv nicht wollen (zum Beispiel, wenn Sie eine Liste solcher Werte behalten wollen, und sie werden anders sein) generische Typen) –

0

Ich glaube Sie eine Sammlung von Instanzen verschiedener RegistrationValue s-abgeleiteten Klassen haben wollen und der Lage sein, es zu durchlaufen und für für jedes Element unterschiedliche Art zu haben. Das ist ziemlich unmöglich.

Sie müssen jedes Element weiterhin in den Typ konvertieren, der Ihnen bekannt ist, da beim Iterieren der Auflistung Verweise auf Ihren Basistyp zurückgegeben werden (ParameterRegistrationValue - dieser wird vom IList Typparameter angegeben). Es wird also keinen wirklichen Unterschied machen, wenn man über die nicht generische object Liste iteriert.

Und wenn Sie dieses Casting für jeden Parameter (Sie kennen alle Typen) sicher tun können, brauchen Sie wahrscheinlich keine Sammlung wie diese - es ist besser, eine Klasse zu haben, die alle Parameter einkapselt ein Typ, so dass Sie es mit starken Typen, mit IntelliSense etc. wie folgt nennen können:

public class ParameterRegistration 
{ 
    public DateTime RegistrationDate { get; set; } 
    public PatientData PatientData { get; set; } 
    public Guid Identifier { get; set; } 
    // ... 
} 
+0

Und was würden Sie dann im PatientData-Objekt speichern? Vielen Dank. – Sam

+0

Nun, ich kenne Ihre Bedürfnisse nicht. Haben Sie nicht irgendein Domain-Objekt, das alle Daten für Ihre 'Registration' darstellen kann, alle möglichen' ParameterRegistrationValue' einkapseln? Es kann eine Menge Daten sein, aber Sie können immer Daten überspringen, die nicht auf eine gegebene Instanz anwendbar sind und bei Bedarf 'null' übergeben. – NOtherDev