Comment dois-je gérer une situation où j'ai besoin de stocker plusieurs sans rapport avec les types, mais de fournir des types spécifiques à la demande?

StackOverflow https://stackoverflow.com/questions/54219

  •  09-06-2019
  •  | 
  •  

Question

Je suis en train de travailler sur un éditeur pour les fichiers qui sont utilisés par un interne important outil de test que nous utilisons.L'outil lui-même est immense, compliqué, et refactoring ou la réécriture prendrait plus de ressources que nous sommes en mesure de consacrer à elle pour un futur proche, de sorte que mes mains sont liées quand il s'agit de grandes modifications.Je dois utiliser un .NET de la langue.

Les fichiers XML sérialisé versions des quatre classes qui sont utilisées par l'outil (appelons-les A, B, C et D).Les classes forment une structure en arbre quand tout est bien.Notre éditeur des œuvres de chargement d'un ensemble de fichiers, la désérialisation d'entre eux, de travailler les relations entre eux, et de garder la trace de tous les mauvais états, on peut trouver.L'idée est de nous éloigner de la main l'édition de ces fichiers, qui introduit des tonnes d'erreurs.

Pour un type particulier d'erreur, je tiens à maintenir une collection de tous les fichiers qui ont le problème.Tous les quatre classes peut avoir le problème, et j'aimerais réduire la duplication de code autant que possible.Une condition importante est que l'utilisateur doit être en mesure d'obtenir des éléments dans des ensembles;par exemple, ils ont besoin pour obtenir tous les Un les objets avec une erreur, et de leur dire de faire une itération sur l'ensemble de la collection et de choisir ce qu'ils veulent, c'est inacceptable par rapport à un GetAs() la méthode.Donc, ma première pensée a été de faire un générique élément liées à l'objet désérialisé et certaines métadonnées pour indiquer l'erreur:

public class ErrorItem<T>
{
    public T Item { get; set; }
    public Metadata Metadata { get; set; }
}

Ensuite, j'aurais une classe de collection qui pourrait contenir tous les éléments erreur, avec les méthodes d'aide à extraire les éléments d'une classe spécifique lorsque l'utilisateur a besoin d'eux.C'est là que les problèmes commencent.

Aucun des classes héritent d'un ancêtre commun (autres que Object).C'était probablement une erreur de la conception initiale, mais j'ai passé quelques jours pour y réfléchir et les classes n'ont pas vraiment de point commun qu'un GUID de la propriété qui permet d'identifier chaque objet de manière à ce que je peux voir pourquoi le concepteur initial n'a pas les relier par héritage.Cela signifie que l'unité d'erreur de la collection aurait besoin de stocker ErrorItem<Object> les objets, puisque je n'ai pas de base de la classe ou de l'interface de restreindre ce qui vient dans.Cependant, ce qui rend l'idée de cette collection unifiée un peu louche pour moi:

Public Class ErrorCollection
{
    public ErrorItem<Object> AllItems { get; set; }
}

Cependant, cela a des conséquences sur l'interface publique.Ce que je veux vraiment est le retour de l'appropriées ErrorItem type générique comme ceci:

public ErrorItem<A>[] GetA()

C'est impossible parce que je ne peut stocker que de ErrorItem<Object>!J'ai dépassé quelques solutions de contournement dans ma tête;la plupart du temps ils comprennent la création d'un nouveau ErrorItem du type approprié à la volée, mais il se sent juste le genre de laid.Une autre pensée qui a été à l'aide d'un Dictionary pour conserver les éléments organisés par type, mais il ne semble pas encore droit.

Est-il une sorte de modèle qui pourrait m'aider ici?Je sais que la façon la plus simple de résoudre ce problème est d'ajouter une classe de base qui A, B, C, et D en tirer, mais je suis en train d'avoir un impact sur l'outil d'origine que possible.Est le coût de toute solution de contournement assez grande que je devrais pousser à changer l'outil initial?

Était-ce utile?

La solution

Si A, B, C et D n'ont rien en commun à l'ajout d'une classe de base ne sera pas vraiment vous obtenir quoi que ce soit.Il va juste être une classe vide et dans l'effet sera le même que l'objet.

Je venais de créer un ErrorItem classe sans les génériques, en faire un Élément de l'objet et faire un peu de moulage lorsque vous souhaitez utiliser les objets référencés.Si vous souhaitez utiliser l'une des propriétés ou des méthodes de la A, B, C ou D autre classe que le Guid vous auriez dû les jeter de toute façon.

Autres conseils

Est-ce ce que vous recherchez?

private List<ErrorItem<object>> _allObjects = new List<ErrorItem<object>>();

public IEnumerable<ErrorItem<A>> ItemsOfA
{
    get
    {
        foreach (ErrorItem<object> obj in _allObjects)
        {
            if (obj.Item is A)
                yield return new ErrorItem<A>((A)obj.Item, obj.MetaData);
        }
    }
}

Si vous souhaitez mettre en cache les ItemsOfA vous pouvez facilement le faire:

private List<ErrorItem<A>> _itemsOfA = null;

public IEnumerable<ErrorItem<A>> ItemsOfACached
{
    if (_itemsOfA == null)
        _itemsOfA = new List<ErrorItem<A>>(ItemsOfA);
    return _itemsOfA;
}

La réponse que je vais jusqu'à présent est une combinaison des réponses de fryguybob et Mendelt Siebenga.

L'ajout d'une classe de base serait juste de polluer l'espace de noms et d'introduire un problème similaire, comme Mendelt Siebenga souligné.Je voudrais obtenir plus de contrôle sur quels éléments peut aller dans la collection, mais j'avais encore besoin de stocker ErrorItem<BaseClass> et continue de faire de casting, alors j'aimerais avoir un problème un peu différent avec la même cause.C'est pourquoi j'ai choisi le post comme réponse:il souligne que je vais devoir faire un peu de jette n'importe quoi, et BAISER voudrait que le supplément de la classe de base et les génériques sont de trop.

J'aime fryguybob la réponse n'est pas la solution, mais pour me rappeler à l'ordre yield return, qui fera un non-version en cache plus facile à écrire (j'allais utiliser LINQ).Je pense qu'une version mise en cache est un peu plus sage, même si le rendement attendu des paramètres ne sera pas à la non mise en cache version nettement plus lent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top