2017-05-19 1 views
1

Je désérialise certaines réponses JSON et les place dans l'une des deux classes primaires selon qu'un seul objet est renvoyé ou si une liste d'objets est renvoyée. J'utilise actuellementClasse abstraite avec propriétés tapées par classe

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; } 
} 

pour contenir la (les) réponse (s). Cependant, je sais que ce n'est pas le meilleur moyen, d'autant plus que je dois utiliser un retour dynamique dans la classe appelante pour gérer les deux types de réponses possibles. Je pense qu'une classe abstraite (ou une interface?) Est une meilleure façon de le faire, mais je ne sais pas comment l'implémenter. Suis-je sur la bonne voie & si oui, comment puis-je construire la classe abstraite et faire l'héritage?

Répondre

0

Créez une conception basée sur des réponses multiples, c'est-à-dire en conservant/renvoyant une liste même s'il n'y a qu'un seul objet. Cela élimine l'idée de design selon laquelle il existe un cas particulier. Et le code résultant sera plus cohérent et robuste.

L'accent doit être mis sur l'objet lui-même - ce que vous en faites après la réhydratation. Pas sur le hasard trivial que j'ai un objet ou plus d'un. Cette distinction n'est pas différente que "4 objets ou pas 4 objets." L'abstraction du conteneur dans une classe unique rend nécessairement le travail avec les objets plus important, l'accent de votre conception.

modifier

penser de cette façon. Les objets désérialisés uniques ou multiples sont une conséquence du nombre d'objets à désérialiser. C'est un détail d'implémentation qui n'est pas en rapport avec l'utilisation réelle des objets (désérialisés). Encapsuler les détails d'implémentation, c'est-à-dire les masquer du code client. Donner aux clients des classes et des méthodes qui expriment des fonctionnalités dans des termes de "domaine métier".

modifier fin


Modifier

... Je suis d'avoir à utiliser un retour dynamique dans la classe d'appel pour traiter les deux types de réponses possibles. Je pense qu'une classe abstraite (ou une interface?) Est une meilleure façon de le faire, mais je ne sais pas comment l'implémenter.

points principaux:

  • ClientApi transforme l'objet désérialisé à la classe souhaitée.

    • Deux API!
      • constructeurs appelés par l'objet de-hydratant
      • Masquer le constructeur par défaut pour assurer objet valide instanciation
      • GetDeHydratedJsonThingy appelé par le client « en utilisant ».
  • désérialiseur et "à l'aide" client sont découplés grâce à la classe ClientApi.

    • De-hydratation travaille avec DeserializedResults objets
    • "Utilisation" client ne se soucie que MultipleResponse objets
  • "en utilisant" client traite avec un seul type de retour.

P.S. Après avoir écrit ceci, j'ai réalisé qu'une seule classe "Response" est nécessaire, maintenant que la classe ClientApi encapsule les instanciations d'objet. Le code commenté est original.

P.P.S. Ma méthode et les noms de paramètres sont vraiment moche. Utilisez les noms qui ont une signification dans le domaine du problème. c'est-à-dire la terminologie de l'utilisateur.

.

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; 
    } 
} 

fin Modifier

+0

Je dois me différencier pour la désérialisation. J'obtiens des erreurs si j'essaie de désérialiser une liste par rapport à un seul objet. C'est le moyen le plus simple et le moins coûteux que je puisse imaginer. – gilliduck

+1

Ok, vous devez, mais pourquoi le code client? Faites ce que vous avez à faire, mais transmogrifiez-le pour que les clients ne s'occupent que d'une seule chose. N'exposez pas vos problèmes d'implémentation aux clients. Donnez-leur une API propre et cohérente avec laquelle travailler. – radarbob

+1

"... c'est la manière la plus simple et la moins lourde ..." 1 La classe est plus simple que 2. Un type de retour est plus simple que 2. Pensez à ce que le client est forcé de faire. Je vois le potentiel d'au moins un code de traitement spécial. Vous rendez l'API plus complexe, c'est ce qui compte. – radarbob

0

Vous pouvez essayer ce qui suit avec une base générique de classe abstraite

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

Les implémentations concrètes hériteraient de la réponse de base commune.

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; } 
}