Come determinare il tipo di oggetto di classe derivata su lazy-load da un oggetto associato

1

Sto modellando un sistema che è una combinazione di due repository di dati distinti ma simili **: uno contenente i dati sui brevetti e uno contenente i dati sui marchi. C'è una sovrapposizione molto grande nello schemae, cioè ogni database contiene gran parte dello stesso tipo di informazioni.

Per essere più specifici: ci sono "casi" - casi di brevetti e casi di marchi - i dati per ciascuno sono memorizzati nel rispettivo database. Un caso ha molti degli stessi dati di base indipendentemente dal fatto che si tratti di un caso di brevetto o di un marchio, ma, naturalmente, ci sono anche dati che sono unici per ogni tipo di caso. Ci sono anche "azioni" associate a ogni caso. A differenza dei casi, tuttavia, le azioni condividono lo stesso identico schema sia nel database dei brevetti che nei marchi.

Nella mia applicazione, ho una classe Case con PatentCase e TrademarkCase che ne derivano. Un Case ha una collezione di oggetti Action . Anche Action ha un riferimento al caso associato.

Utilizzo il caricamento pigro in entrambe le direzioni: Case con il suo Action s associato e Action con il suo Case associato. Ora so che potrebbe semplicemente usare l'iniezione di dipendenza per dare a ogni Action un riferimento al suo Case associato. Tuttavia, ciò che non mostro qui è che un Action potrebbe essere usato altrove e potrebbe essere caricato prima che venga caricato il caso associato, quindi il caricamento pigro bidirezionale.

Dove mi trovo a lottare è come capire quale tipo di Case caricare a pigro da Action (vedi commento in CaseLoader.GetCase ). Non voglio memorizzare il tipo di azione (o faccio?) Quando l'azione viene caricata dal rispettivo repository, perché l'azione ha una preoccupazione che non dovrebbe avere, cioè da quale repository proviene. Ma non riesco a pensare a un modo migliore per farlo.

Qual è il modo migliore per determinare quale tipo di Case è associato a Action ?

Ecco il codice:

public abstract class Case
{
    private ReadOnlyCollection<Action> _associatedActions;

    public ReadOnlyCollection<Action> AssociatedActions
    {
        get
        {
            if (_associatedActions == null) _associatedActions = ActionLoader.GetActions(this);
            return _associatedActions;
        }
    }
}

public class PatentCase : Case
{
    // patent stuff
}

public class TrademarkCase : Case
{
    // trademark stuff
}

public class Action
{
    private int _associatedCaseID;
    private Case _associatedCase;

    public Case AssociatedCase
    {
        get
        {
            if (_associatedCase == null) _associatedCase = CaseLoader.GetCase(this);
            return _associatedCase;
        }
    }
}

internal static class ActionLoader
{
    internal static ReadOnlyCollection<Action> GetActions(Case forCase)
    {
        if (forCase is PatentCase)
        {
            // retrieve actions from data layer, and return.
        }
        else if (forCase is TrademarkCase)
        {
            // retrieve actions from data layer, and return.
        }
        else
        {
            throw new ArgumentException("The argument is not a derivation of case that this method knows about.");
        }
    }
}

internal static class CaseLoader
{
    internal static Case GetCase(Action forAssociatedAction)
    {
        // what is the best way to determine here what type of case is associated with the action?
    }
}

** I database appartengono a un fornitore di terze parti. Mentre, in un altro mondo, potrei immaginare tutto ciò che esiste in un database in cui tutti i dati comuni sono organizzati meglio (rendendo così più facile il mio compito), la realtà è che vendono i loro prodotti come pacchetti separati - abbiamo acquistato il loro "brevetto" e pacchetti "marchio" - quindi i database separati. Sto semplicemente cercando di creare un wrapper che li combini efficacemente.     
posta rory.ap 25.02.2016 - 17:33
fonte

1 risposta

1

Suggerirei di avere una classe CaseReference che contenga tutte le informazioni richieste per trovare il caso (DB di destinazione e ID del caso). Hai due opzioni con questo approccio:

class CaseReference {
    public CaseDatabase Database { get;set; } // enum which identifies the target database
    public int CaseId { get;set; }
}

Oppure puoi usare il polimorfismo:

abstract class CaseReference {
    public int CaseId { get;set; }
    // other methods which provide interface for logic to connect to database
}
class PatentCaseReference : CaseReference { ... }
class TrademarkCaseReference : CaseReference { ... }

Quindi la tua classe Action deve memorizzare un CaseReference anziché solo l'ID del caso. Il tuo CaseLoader può esaminare il valore di CaseReference.Database per determinare quale database aprire nel primo caso o rinviare alla logica nella classe CaseReference nel secondo caso.

    
risposta data 25.02.2016 - 20:35
fonte

Leggi altre domande sui tag