Come devo gestire una situazione in cui ho bisogno di memorizzare diversi estranei tipi, ma forniscono specifici tipi di domanda?

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

  •  09-06-2019
  •  | 
  •  

Domanda

Sto lavorando su di un editor per i file che vengono utilizzati da un importante test interni strumento che utilizziamo.Lo strumento in sé è grande, complicato, e refactoring o riscrittura vorrebbe più risorse di quanto siamo in grado di dedicare ad esso per il prevedibile futuro, così le mie mani sono legate quando si tratta di grandi modifiche.Devo utilizzare un .NET lingua.

Il file XML serializzato versioni di quattro classi che vengono utilizzate dallo strumento (chiamiamoli A, B, C, e D).Le classi che formano una struttura ad albero, quando tutto va bene.Il nostro editor di opere di caricamento di un set di file, la deserializzazione di loro, lavorando i rapporti tra di loro, e tenere traccia di eventuali stati cattivi si possono trovare.L'idea è, per noi, per allontanarsi da una mano-la modifica di questi file, che introduce tonnellate di errori.

Per un particolare tipo di errore, mi piacerebbe mantenere una raccolta di tutti i file che hanno il problema.Tutte e quattro le classi possono avere il problema, e vorrei ridurre la duplicazione di codice, per quanto possibile.Un requisito importante è che l'utente deve essere in grado di ottenere gli elementi in gruppi;per esempio, hanno bisogno di ottenere tutti gli oggetti con un errore, e dicendo loro di scorrere l'intera collezione e scegliere quello che si desidera è inaccettabile rispetto ad un GetAs() metodo.Così, il mio primo pensiero è stato quello di fare un generico elemento che ha collegato l'oggetto deserializzato e alcuni metadati per indicare l'errore:

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

Quindi, mi piacerebbe avere una collezione di classe che potrebbe contenere tutte le voci di errore, con metodi di supporto per estrarre gli elementi di una classe specifica quando l'utente ha bisogno di loro.Questo è dove iniziano i problemi.

Nessuna delle classi ereditano da un antenato comune (diverso da Object).Questo è stato probabilmente un errore di progettazione iniziale, ma ho trascorso un paio di giorni per pensarci e le classi in realtà non hanno molto in comune diverso da un GUID proprietà che identifica in modo univoco ogni elemento in modo che posso vedere perché il progettista originale non metterle in relazione con l'eredità.Questo significa che i unificata di errore raccolta sarà necessario conservare ErrorItem<Object> oggetti, dal momento che non ho una base della classe o interfaccia per limitare ciò che entra.Tuttavia, questo rende l'idea di questa raccolta un po ' scarso di me:

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

Tuttavia, questo non ha conseguenze sull'interfaccia pubblica.Quello che voglio veramente è quello di restituire un'appropriata ErrorItem tipo generico come questo:

public ErrorItem<A>[] GetA()

Questo è impossibile, perché posso solo negozio ErrorItem<Object>!Ho superato alcune soluzioni alternative nella mia testa;per lo più essi includono la creazione di un nuovo ErrorItem del tipo on-the-fly, ma si sente solo tipo di brutto.Un altro pensiero è stato utilizzando un Dictionary mantenere le informazioni organizzate per tipo, ma ancora non mi sembra giusto.

C'è qualche motivo che mi potrebbe aiutare qui?So che il modo più semplice per risolvere questo è quello di aggiungere una classe di base A, B, C, e D derivano, ma sto cercando di avere come minimo l'impatto sull'originale strumento possibile.È il costo di qualsiasi soluzione abbastanza grande che mi dovrebbe spingere a modificare l'iniziale strumento?

È stato utile?

Soluzione

Se A, B, C e D non hanno nulla in comune con l'aggiunta di una classe base non ottenere nulla.Sarà solo una classe vuota e in effetto sarà lo stesso come oggetto.

Mi piacerebbe creare un ErrorItem classe senza i farmaci generici rendere la Voce di un oggetto e fare qualche casting quando si desidera utilizzare gli oggetti a cui fa riferimento.Se si desidera utilizzare uno dei metodi o proprietà di A, B, C o D classe diversa Guid avrebbe dovuto cast, comunque.

Altri suggerimenti

Questo è ciò che stai cercando?

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

Se si desidera memorizzare il ItemsOfA si può facilmente farlo:

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

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

La risposta che ho intenzione finora è una combinazione delle risposte da fryguybob e Mendelt Siebenga.

Aggiunta di una classe di base sarebbe solo inquinare lo spazio dei nomi e introdurre un problema simile, come Mendelt Siebenga sottolineato.Vorrei avere più controllo su ciò che gli elementi possono andare in collezione, ma avrei ancora bisogno di memorizzare ErrorItem<BaseClass> e comunque fare qualche casting, quindi mi piacerebbe avere un problema leggermente diverso con la stessa radice della causa.Questo è il motivo per cui ho scelto il post come risposta:si sottolinea che sto andando a fare un po ' di lanci, non importa cosa, e il BACIO, vorrebbe che l'extra classe base e generici sono troppo.

Mi piace fryguybob la risposta non la soluzione ma per ricordare a me circa yield return, che farà un non-cache versione più facile da scrivere (stavo per usare LINQ).Penso che una versione in cache è un po ' più saggio, anche se le prestazioni previste per i parametri non non in cache versione significativamente più lento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top