2017-05-19 4 views
1

Ich deserialisiere einige JSON-Antworten und lege sie in eine von zwei primären Klassen ein, abhängig davon, ob ein einzelnes Objekt zurückgegeben wird oder ob eine Liste von Objekten zurückgegeben wird. Ich verwende derzeitAbstrakte Klasse mit typisierten Klasseneigenschaften

public class MultiResponse 
{ 
    public List<DeserializedResult> Result { get; set; } 
} 

public class SingleResponse 
{ 
    public DeserializedResult Result { get; set; } 
} 

public class DeserializedResult 
{ 
    public string Id { get; set; } 
    public string AccountName { get; set; } 
} 

, um die Antwort (en) enthalten. Aber ich weiß, dass es nicht der beste Weg ist, besonders da ich eine dynamische Rückkehr in der aufrufenden Klasse verwenden muss, um mit den zwei Arten von möglichen Antworten umzugehen. Ich denke, eine abstrakte Klasse (oder Schnittstelle?) Ist ein besserer Weg, dies zu tun, aber ich weiß nicht, wie ich es umsetzen soll. Bin ich auf dem richtigen Weg & wenn ja, wie konstruiere ich die abstrakte Klasse und mache die Vererbung?

Antwort

0

Erstellen Sie ein Design basierend auf Mehrfachantworten - d. H. Das Halten/Zurückgeben einer Liste, selbst wenn nur ein Objekt vorhanden ist. Es beseitigt den Design "Hinweis", dass es einen speziellen Fall gibt. Und der resultierende Code wird konsistenter und robuster sein.

Der Fokus sollte auf dem Objekt selbst liegen - was man damit nach der Rehydratation macht. Nicht auf den trivialen Zufall, dass ich ein Objekt oder mehr als eins habe. Diese Unterscheidung ist nicht anders als "4 Objekte oder nicht 4 Objekte".

Das Abstrahieren des Containers auf eine einzelne Klasse macht die Arbeit mit den Objekten im Fokus, die Betonung Ihres Designs.

bearbeiten

Betrachten Sie es auf diese Weise. Einzelne oder mehrere deserialisierte Objekte sind eine Konsequenz davon, wie viele Objekte zu deserialisieren waren. Es ist ein Implementierungsdetail, das für die tatsächliche Verwendung der (deserialisierten) Objekte nicht relevant ist. Encapsulate Implementierung Details, das heißt, verstecken sie aus dem Client-Code. Geben Sie den Clients Klassen und Methoden an, die die Funktionalität in "Geschäftsdomänen" ausdrücken.

Ende bearbeiten


bearbeiten

... Ich habe eine dynamische Rückkehr in die aufrufende Klasse verwenden möglich mit den zwei Arten von Reaktionen zu behandeln. Ich denke, eine abstrakte Klasse (oder Schnittstelle?) Ist ein besserer Weg, dies zu tun, aber ich weiß nicht, wie ich es umsetzen soll.

Hauptpunkte:

  • ClientApi verwandelt das entserialisierten Objekt an die gewünschte Klasse.

    • Zwei APIs!
      • Bauer durch die de-feuchtigkeitsspendende Objekt namens
      • ausblenden Standardkonstruktors gültig Objektinstanziierung
      • GetDeHydratedJsonThingy durch die „mit“ Client aufgerufen, um sicherzustellen.
  • Deserializer und "mit" Client dank der ClientApi Klasse entkoppelt.

    • De-Trink arbeitet mit DeserializedResults Objekte
    • "Verwendung" Client nur kümmert sich um MultipleResponse Objekte
  • mit nur einem Rückgabetyp Client-Angebote "mit".

P.S. Nachdem ich das geschrieben habe, wurde mir klar, dass nur eine "Response" -Klasse benötigt wird, jetzt, da die Klasse ClientApi die Objekt-Instanzen kapselt. Der kommentierte Code ist original.

P.P.S. Meine Methoden- und Parameternamen sind wirklich mies. Verwenden Sie Namen, die eine Bedeutung in der Problemdomäne haben. d.h. Benutzerterminologie.

.

public class ClientApi { 
    protected MultiResponse MoreThanOne { get; set; } 
    // protected SingleResponse OnlyOne { get; set; } 

    protected ClientApi (); 

    public ClientApi (List<DeserializedResult> theList) { 
     if (theList == null) throw ArgumentNullException("error message here"); 

     // add overloaded constructors to MultiResponse class. 
     MoreThanOne = new MultiResponse (theList); 
     // OnlyOne = null; 
    } 

    public ClientApi (DeserializedResult onlyOne) 
     if (onlyOne == null) throw ArgumentNullException("error message here"); 

     MoreThanOne = new MultiResponse(onlyOne); 
     // OnlyOne = onlyOne; 
    } 

    ///<summary> 
    /// Always returns an object. The list may be empty, 
    /// but never null 
    ///</summary> 
    public MultiResponse GetDeHydratedJsonThingy() { 
     MultiResponse HereYaGo = new MultiResponse(); 
     // if (MoreThanOne !=null) HereYaGo.AddRange(MoreThanOne); 
     // if (OnlyOne != null) HereYaGo.Add(OnlyOne); 

     HereYaGo.AddRange(MoreThanOne.Result); 
     return HereYaGo; 
    } 
} 

Ende bearbeitet

+0

Ich muss für die Deserialisierung unterscheiden. Ich bekomme Fehler, wenn ich versuche, eine Liste gegen ein einzelnes Objekt zu deserialisieren. Dies ist der einfachste Weg, den ich mir vorstellen kann. – gilliduck

+1

Ok, SIE müssen, aber warum sollte der Client Code? Tu, was du tun musst, aber verändere es, damit die Kunden nur mit einer Sache umgehen. Setzen Sie Ihre Implementierungsprobleme den Clients nicht aus. Geben Sie ihnen eine saubere, konsistente API, mit der sie arbeiten können. – radarbob

+1

"... das ist der einfachste, am wenigsten Overhead-Weg ..." 1 Klasse ist einfacher als 2. Ein Rückgabetyp ist einfacher als 2. Denken Sie darüber nach, was der Client tun muss. Ich sehe das Potential für zumindest einen speziellen Handling-Code. Sie machen die API komplexer, darauf kommt es an. – radarbob

0

Sie den folgend mit einer allgemeinen Basis

abstrakte Klasse versuchen
public abstract class Response<T> { 
    public T Result { get; set; } 
} 

Die konkreten Implementierungen von der gemeinsamen Basis Antwort erben würden.

public class Response : Response<object> { 
    public object Result { get; set; } 
} 

public class MultiResponse : Response<List<DeserializedResult>> { 
    public List<DeserializedResult> Result { get; set; } 
} 

public class SingleResponse : Response<DeserializedResult> { 
    public DeserializedResult Result { get; set; } 
} 
Verwandte Themen