Due origini dati unite

2

Ho un editor di giochi salvati. Usa una libreria in grado di leggere il file e restituirlo sotto forma di un oggetto. All'interno di quell'oggetto c'è un oggetto ItemSave.

Inoltre, per essere in grado di interpretare i dati nell'oggetto ItemSave, ho bisogno di più informazioni (da un xml) che ottengo con un metodo nel mio codice che restituisce l'oggetto ItemData. Hanno tutti campi diversi, ad eccezione del campo "id". Il campo id viene utilizzato per stabilire la connessione tra i due.

Per ogni variante ItemData (ce ne sono circa 1500, potrebbe espandersi, fuori dal mio controllo) Posso avere numerosi oggetti ItemSave (ad esempio una pistola sarà sempre chiamata una pistola e avrà sempre una dimensione di clip di 10, ma il numero di proiettili caricati può variare, ecc.)

Come puoi vedere, una classe è piuttosto inutile senza l'altra, quindi mi piacerebbe combinarle.

Attualmente, ho una classe ItemBinder che contiene il riferimento a ItemData e ItemSave e ha anche i campi di entrambi per appiattirlo (in modo che io possa accedere ai dati con ItemBinder.Value, non con ItemBinder.ItemSave.Value). Tuttavia, questo è un codice errato ed è difficile da mantenere.

Potrei rilasciare tutti i campi nell'oggetto ItemBinder e avere solo i due riferimenti e soffrire per avere percorsi più lunghi, ma vorrei che ItemBinder sembrasse la "classe" che ha tutti i dati, mentre gli altri due sono nascosti via.

Una ulteriore complicazione è che dovrei definire diversi metodi nella classe ItemBinder che manipolerebbero i dati da entrambe le classi. Questo può o non può essere un problema a seconda della soluzione a questo, se ce n'è uno.

Inoltre, tutti i dati saranno un tipo di riferimento, in modo da semplificare un po 'le cose.

    
posta Karlovsky120 29.09.2016 - 18:52
fonte

2 risposte

1

Come ha detto @FrankHileman, ciò che stai cercando è la delega o forse l'ereditarietà multipla. Né sono caratteristiche che fornisce C #. Tuttavia, è possibile ottenere questo risultato compilando la generazione del codice di tempo (si potrebbe anche fare la generazione di runtime o eventualmente andare in giro con la dinamica, ma prima era meglio in generale per questo genere di cose). Il modo più diffuso per ottenere questo risultato è Modelli T4 . Non ho un C # IDE a portata di mano, quindi non posso dare una risposta completa a questa risposta, ma ho fatto cose simili in passato. La procedura generale sarebbe:

  1. Configura un modello T4 da integrare nel tuo progetto ( questo è fatto facilmente con qualsiasi VS moderno ).
  2. Scrivi un modello T4 per generare una percentuale parziale diItemBinder ( per esempio ).
  3. Nel tuo file, definisci l'altra metà di ItemBinder con i membri non delegati.

Compirai 2 tramite riflesso . Per ognuno di ItemData e ItemSave otterresti tutte le proprietà pubbliche (ad esempio typeof(ItemData).GetProperties() ) su di loro e emettere una stringa che delega quella proprietà, ad es. attraverso un metodo come

string DelegateProperty(PropertyInfo property, string backingMember) 
{
    string declaration = String.Format("public {0} {1} {{ ", property.PropertyType.FullName, property.Name);
    if (property.GetGetMethod() != null)
    {
        declaration += String.Format("get {{ return {0}.{1}; }} ", backingMember, property.Name;
    }
    if (property.GetSetMethod() != null)
    {
        declaration += String.Format("set {{ {0}.{1} = value; }} ", backingMember, property.Name;
    }
    declaration += "}";
    return declaration;
}

Scriveresti anche un metodo simile per i metodi, beh, (questo è più coinvolto). Potrebbe essere necessario approfondire ulteriormente se si desidera acquisire gli attributi su tali proprietà o implementare anche interfacce di tipo.

Sono un po 'in due a proposito di quanto sia saggio. Da un lato avere i computer generano codice completamente privo di senso mentale ha un sacco di aspetti positivi (meno cruft da leggere, nessuna possibilità di errori stupidi), ma d'altra parte si sta complicando il processo di costruzione, legandosi a strumenti particolari e potenzialmente rendendo le cose un un po 'più complicato per i futuri manutentori.

    
risposta data 29.01.2017 - 07:18
fonte
0

Capisco perché ItemBinder può avere senso, dato che ci sono molti ItemSave per ItemData . E infatti sembra che ItemData non cambierà durante la vita dell'applicazione. In questo caso, aggiungere idealmente una proprietà ItemData in ItemSave , ma non è possibile modificare ItemSave (e fare una classe derivata è inutile perché il codice di terze parti non la utilizzerà). Quindi crei ItemBinder .

Tuttavia ItemBinder non è una buona soluzione, in quanto aggiunge un nuovo problema di manutenzione con le proprietà di convenienza.

Suggerirei di creare un metodo di estensione per ItemSave che ti permetta di ottenere l'appropriato ItemData e quindi di continuare a utilizzare ItemSave direttamente. Per ottenere informazioni da ItemData chiama il metodo di estensione. Modifica: i tuoi metodi aggiuntivi potrebbero essere anche metodi di estensione.

Ovviamente useresti un dizionario per memorizzare ItemData per il recupero rapido.

    
risposta data 01.10.2016 - 06:00
fonte

Leggi altre domande sui tag