Ho una situazione in cui ho una libreria esterna. In breve, ho bisogno di essere in grado di adattare il mio tipo al loro e il loro al mio. La libreria ha una raccolta come questa:
interface IExternalCollection
{
void Add(IExternal item);
IExternal Get(int index);
}
Ora, iniziamo spiegando la soluzione semplice più . Ho un adattatore normale per questa raccolta e adattatori regolari per IExternal e IInternal:
interface IInternalCollection
{
void Add(IInternal item);
IInternal Get(int index);
}
class InternalCollectionAdapter : IInternalCollection
{
private IExternalCollection collection;
public InternalCollectionAdapter(IExternalCollection collection)
{
this.collection = collection;
}
public void Add(IInternal item)
{
collection.Add(new ExternalAdapter(item));
}
public IInternal Get(int index)
{
return new InternalAdapter(collection.Get(index));
}
}
Questa soluzione richiede 2 adattatori per lo stesso tipo e il mio ExternalAdapter adatta InternalAdapter (non esiste un tipo concreto interno). Quel che è peggio è che la mia interfaccia interna ha solo 2 metodi, ma l'interfaccia esterna ha molti (15-ish). Nel mio codice, ho solo bisogno di questi 2, motivo per cui ho progettato la mia interfaccia per avere solo quelli 2, ma ora ho bisogno di raggruppare la mia interfaccia con tutti e 15 per poter creare ExternalAdapter .
Quindi ho pensato, sicuramente c'è un modo migliore. Ho letto su 2WayAdapter e ha il seguente aspetto:
class TwoWayAdapter : External, IInternal
{
public void Show()
{
base.Display();
}
}
Questo mi permette di scrivere un CollectionAdapter in questo modo:
class InternalCollectionAdapter : IInternalCollection
{
private IExternalCollection collection;
public InternalCollectionAdapter(IExternalCollection collection)
{
this.collection = collection;
}
public void Add(IInternal item)
{
collection.Add((IExternal)item);
}
public IInternal Get(int index)
{
return (TwoWayAdapter)collection.Get(index);
}
}
E chiamalo così:
collection.Add(new TwoWayAdapter());
collection.Get(0);
Funziona, e ho solo bisogno di 1 adattatore per il tipo, e posso progettare la sua API come mi pare.
Tuttavia, questa libreria esterna crea i propri oggetti di tipo Esterno .
Pertanto, quando chiamo Get
sulla raccolta esterna, è possibile che venga restituita un'istanza di recente aggiunta di Esterno , rendendo impossibile eseguire il cast su TwoWayAdapter .
La mia ultima soluzione è consentire l'accesso a adaptee , come questo:
class InternalAdapter : IInternal
{
private IExternal adaptee;
public Object Adaptee { get { return adaptee; } }
public InternalAdapter(IExternal adaptee)
{
this.adaptee = adaptee;
}
public void Show()
{
adaptee.Display();
}
}
Ciò cambierà il mio CollectionAdapter in questo modo:
class InternalCollectionAdapter : IInternalCollection
{
private IExternalCollection collection;
public InternalCollectionAdapter(IExternalCollection collection)
{
this.collection = collection;
}
public void Add(IInternal item)
{
collection.Add((IExternal)item.Adaptee);
}
public IInternal Get(int index)
{
return new InternalAdapter(collection.Get(index));
}
}
Come puoi vedere, questo richiede che la mia interfaccia interna abbia una proprietà Object Adaptee { get; }
, che ha un odore davvero molto cattivo.
Posso solo immaginare che questa situazione sia venuta fuori molte volte, ma i miei sforzi su Internet sono stati vani.
Vorrei una soluzione in cui posso mantenere pulita la mia API da tutti i metodi esterni di cui non ho bisogno e preferibilmente una in cui Adaptee rimane nascosto.
Modifica
Dopo aver riflettuto un po 'di più su questo problema, ho trovato una soluzione che sembra all'altezza delle mie esigenze, vale a dire un'API pulita che non include elementi di cui non ho bisogno e che non espone il < strong> adaptee .
Is è una combinazione delle mie precedenti iterazioni e va come follews:
-
Per adattare il loro tipo al mio, utilizzo un adattatore regolare
class InternalAdapter : IInternal { private IExternal adaptee; public InternalAdapter(IExternal adaptee) { this.adaptee = adaptee; } public void Show() { adaptee.Display(); } }
-
Per adattare questo tipo alla loro, creo un TwoWayAdapter .
class TwoWayAdapter : External, IInternal { public void Show() { base.Display(); } }
-
Quindi il mio CollectorAdapter ha il seguente aspetto:
class InternalCollectionAdapter : IInternalCollection { private IExternalCollection collection; public InternalCollectionAdapter(IExternalCollection collection) { this.collection = collection; } public void Add(IInternal item) { collection.Add((IExternal)item); } public IInternal Get(int index) { return new InternalAdapter(collection.Get(index)); } }
Ora potresti notare che questa soluzione ha i suoi problemi, vale a dire, non posso get
uno dei loro tipi, quindi convertirla in miniera, riconvertirla e add
nella loro raccolta.
Questa soluzione funziona nel mio caso in questo progetto solo perché get
recupera una nuova istanza e add
è usata solo con una nuova istanza (aggiunta da me), cioè lo stesso oggetto non è getted
e added
.
Il motivo per cui ho reso questo un edit e non una risposta è che, questo non risolve il problema più generale che propongo in questa domanda.
Solo per chiarire quello che sto chiedendo: Mi piacerebbe conoscere articoli, blog o libri che risolvano questo problema con una tecnica o un modello. Mi piacerebbe anche che qualcuno potesse fare riferimento a ciò che hanno fatto in situazioni precedenti.