C # Iniezione di dipendenza con motivo adattatore

3

Nel seguente esempio di codice, ho un client che funziona attraverso un controller. Nel mio caso specifico, il controller stabilisce una sessione su un bus GPIB . Un'istanza di questo viene quindi iniettata nella classe client, che nel mio caso è un dispositivo. La classe client sa cosa dire al dispositivo e usa il controller per passare quei messaggi al dispositivo.

Dove trovo nei guai ci sono vari modi per parlare al dispositivo. Ho creato finora ITextReader, ITextWriter, IBinaryReader, IBinaryWriter e potrebbero essercene altre in futuro. Le implementazioni di queste interfacce vengono eseguite nell'assieme dell'adattatore, poiché questo è l'unico assembly che sa come parlare con l'adaptee. Il controller e il client hanno solo riferimenti sull'assembly controller.api.

In che modo il client chiede un'istanza di TextReader dell'adattatore, a cui non ha alcun riferimento? Immagino ci sia una combinazione di utilizzo di un pattern factory e di un contenitore IoC (usando Unity), ma non riesco a trovare un progetto in cui il client possa ottenere un'istanza di una di queste implementazioni reader \ writer.

Assieme adattatore:

public class Adapter : IAdapter
{
    public class Adapter(IAdaptee adaptee){..}
}

public class TextReader : TextReaderBase, ITextReader
{
    TextReader(IController controller)
    : base(controller)
    {..}

}

Controller.Api Assembly:

public interface IAdapter{...}
public interface ITextReader{...}
public interface ITextWriter{...}

Controller Assembly:

public class Controller : IController 
{
    Controller (IAdapter adapter){...}
}

public abstract class TextReaderBase : ITextReader
{
    TextReaderBase(IController controller){..}
}

Assemblea clienti:

public class Client : IClient
{
    Client (IController controller){...}
}

Modificato il 6/6/2015:

Dovrei chiarire cosa sto cercando di fare. La libreria di terze parti (adaptee) ha funzioni di basso livello per leggere, scrivere, aprire connessioni, ecc. Le classi di alto livello per stabilire connessioni, leggere e scrivere sono quelle a cui mi riferivo come controller. L'adattatore adatta la libreria di terze parti a questo controller. Ho realizzato interfacce aggiuntive per rappresentare il lettore / autore di basso livello come IAdapterReader e IAdapterWriter.

I client lavorano esclusivamente attraverso il controller, non conoscendo nulla degli adattatori di basso livello. Nella mia attuale progettazione, stavo progettando di avere un servizio che legge un file di configurazione per trovare l'adattatore da istanziare e l'indirizzo del dispositivo. Crea un'istanza di questo adattatore, lo inserisce nella classe controller e quindi inietta l'oggetto controller nel client. Sto chiamando la classe controller qui una "sessione" per rappresentare una connessione ad un indirizzo specifico sul bus. L'idea è che il client sappia cosa dire al dispositivo (comandi e così via) e il controller sa come dirlo (ha accesso al livello fisico).

Per il client di parlare effettivamente con il dispositivo, stavo pensando che avrebbero chiesto un lettore e un'istanza di uno scrittore, ma chiaramente non si tratta dell'iniezione di dipendenza. Affinché il client chieda un lettore \ writer, dovrebbe conoscere l'adattatore in quanto i miei lettori \ scrittori di alto livello completano quelli di basso livello implementati dall'adattatore.

Suppongo che la domanda sia: come fa il cliente ad avere un lettore \ scrittore? Posso pensare a un modo rozzo iniettando nel client ISession, ITextReader, ITextWriter, IBinaryReader, IBinaryWriter e qualsiasi altra interfaccia che potrebbe essere necessaria? L'altro modo è di iniettare solo ISession e fare in modo che ISession abbia un metodo T Resolve<T>(Type type) . L'implementazione di Resolve potrebbe avvenire tramite un contenitore IoC. Potrei cambiare il progetto in modo che, quando viene creato l'oggetto adattatore, registri anche tutte le sue implementazioni con interfacce con un contenitore IoC passato dal livello di servizio.

    
posta LGreenberger 05.06.2015 - 19:59
fonte

1 risposta

1

In questo momento quello che vedo è la seguente catena di dipendenze:

client->controller->adapter->reader->controller

Questo crea una dipendenza circolare.

Usi Dependency Injection per ottenere Inversione di dipendenza. Cioè, quel codice di livello superiore non dipende dall'implementazione del codice di livello inferiore.

Guardando la catena, possiamo attestare che c'è un pezzo di codice, il controller o il lettore di testo, cioè sia alto che basso.

Se il client ha bisogno di utilizzare direttamente il lettore di testo, allora non può essere che anche l'adattatore lo usi, poiché sarebbe necessario iniettarlo più in alto. Piuttosto, ti inietterai l'adattatore nel lettore di testo. E poi iniettare il lettore di testo nel client.

Ma se lo facciamo e manteniamo l'iniezione del controller sia sul client che sul lettore di testo, non stiamo quindi esponendo in modo errato la funzionalità? Perché stai dicendo sia che il lettore di testo è dello stesso livello del controller, sia che il controller si trova a un livello inferiore rispetto al lettore di testo (dato che è stato iniettato)

Infine, perché il client deve accedere al lettore di testo utilizzato dall'adattatore? Se c'è davvero qualcosa che è necessario, puoi fornire un metodo di passaggio che non esponga il fatto che hai il lettore di testo da qualche parte laggiù.

Verifica quale funzionalità sarà di livello inferiore (quale effettivamente fa la scrittura / la lettura) e quale fa le cose di alto livello. Ordinarli più in alto e iniettarli più in basso.

Senza guardare il codice, sto immaginando che l'ordine effettivo sarebbe

client->controller->adapter->text read/write 

E in effetti il lettore / scrittore di testi non ha bisogno di sapere del controller perché è l'unica lettura / scrittura direttamente da / verso il dispositivo. Qualsiasi informazione che il controllore ha che il lettore / scrittore di testi ha bisogno verrà passata attraverso i parametri.

    
risposta data 06.06.2015 - 17:39
fonte

Leggi altre domande sui tag