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.