2012-02-18 16 views
17

Per quanto ho capito, SimpleIoc utilizza il metodo GetInstance per recuperare un'istanza di una classe registrata. Se l'istanza non esiste, la creerà. Tuttavia, questa istanza viene memorizzata nella cache e sempre recuperata, che riproduce lo schema del singleton.SimpleIoc: può fornire una nuova istanza ogni volta che è necessario?

Il mio pensiero è che non è necessario mantenere un'istanza di ViewModel in una memoria se c'è una piccola possibilità che questo ViewModel sarà necessario due volte, quindi mi piacerebbe creare una nuova istanza di esso ogni volta che è necessario . Se abbiamo stiamo avendo una fabbrica per ViewModels, avremo una proprietà come questa:

public MyViewMOdel MyViewModel 
{ 
    get { return SimpleIoc.Default.GetInstance<MyViewModel>(); } 
} 

questo usa pattern Singleton, che credo non sia delle migliori pratiche in tutti i casi. Per aggirare questo problema, mi fare questo:

public MyViewModel MyViewModel 
{ 
    get { return new MyViewModel(SimpleIoc.Default.GetInstance<ISomeInterface>()); } 
} 

Questo ha uno svantaggio che se mai cambiare un costruttore per MyViewModel, ho bisogno di aggiornare questa proprietà anche. Non un grosso problema, ma c'è ancora una sorta di dipendenza.

Come gestisci questo scenario e c'è qualcosa che mi manca? e perché è stato deciso di non restituire l'istanza non condivisa.

E un'altra domanda è, in MVVM Deep dive session Laurent utilizza il metodo GetInstance subito dopo aver registrato un particolare ViewModel, al fine di, come lui dice, assicurarsi che ci sia già un'istanza di questo ViewModel nel contenitore. Perché è esattamente necessario? Se stai recuperando un ViewModel tramite ViewModelLocator, lo creerai quando richiesto. Quindi, perché dovrei averli creati in anticipo?

risposta

9

È possibile ottenere un'istanza diversa ogni volta passando una chiave diversa dal metodo GetInstance. Tuttavia, le istanze verranno memorizzate nella cache, quindi se non si desidera conservarle nella cache, sarà necessario chiamare Annulla registrazione con la chiave corrispondente.

Nella demo, stavo creando la VM in anticipo perché MainVM stava inviando messaggi a SecondaryVM. Poiché la registrazione al Messenger avviene nel costruttore di SecondaryVm, deve essere creata prima che possa iniziare a ricevere messaggi. Il Messenger è ottimo perché è molto disaccoppiato, ma è uno di questi casi in cui è necessario fare del lavoro extra per compensare il disaccoppiamento: The SecondaryVM è il bersaglio dei messaggi anche se MainVM non ha alcun riferimento ad esso.

Spero che abbia senso. Cheers, Laurent

+0

Salve, Laurent, nel caso di un'istanza non condivisa, non importa se si utilizzano chiavi o meno (presumo che non siano presenti più istanze della stessa vista contemporaneamente). In entrambi i casi avrei bisogno di registrare/annullare la registrazione di un modello di vista, quindi avrei bisogno di tenere traccia di loro. Penso che sarebbe ancora un semplice Ioc se esistesse un'opzione di registro per istanze condivise e non condivise. Immagino che sarebbe solo necessario non aggiungere l'istanza creata nel contenitore? – Goran

+2

La soluzione funziona solo se non viene utilizzata l'iniezione del costruttore (che non è una buona cosa). Nel caso in cui il contenitore si assume la responsabilità di iniettare le dipendenze, non c'è modo di dirgli di creare nuove istanze e iniettarle nel costruttore, vero? Sto cercando di evitare di chiamare SimpleIoC.GetInstance() nel mio codice in quanto a seconda del contenitore è una cattiva pratica. Come faccio a dire a SimpleIoC di creare sempre nuove istanze e iniettarle invece di memorizzare nella cache un'istanza? Mi sembra un semplice flag "cache" in SimpleIoC.Register sarebbe sufficiente. – TheAgent

2

SimpleIOC è quello che è ... un semplice contenitore di IOC. Avrà dei piccoli buchi ... ma non sei legato ad esso puoi sempre usare un altro container ICO (ad esempio Unity, Autofac, Castle, ...).

Come Laurent states ha modellato il suo SimpleIOC su this container. Egli menziona anche this container come fonte della sua ispirazione.

Tuttavia, ricordare non è obbligatorio utilizzare un contenitore di sicurezza con MVVM. In molti dei miei progetti ho utilizzato Unity, ma ogni altro contenitore IOC andrà ugualmente bene, è una questione di requisiti, preferenze del cliente e - se tutto il resto fallisce - è chiaro il vecchio gusto personale.

+1

Ciao Obalix, sono consapevole che posso utilizzare un altro contenitore, ma dal momento che sto usando MVVM light, non vorrei introdurre un'altra DLL da caricare, se non ho bisogno di funzionalità avanzate che unità (o qualsiasi altro IoC) offre. Il mio pensiero qui è che questa non è una funzionalità avanzata, che non richiede troppa codifica per implementarla e che è una funzionalità che verrà utilizzata frequentemente. Ero anche interessato a scoprire come altri programmatori che usano SimpleIoc gestiscono i requisiti per le istanze non condivise di un modello di visualizzazione. – Goran

0

Dopo aver lottato con SimpleIoC per fornire nuove istanze ogni volta che viene richiesto un tipo specifico e scoprire questa funzione non è implementata (il metodo basata su chiave accettato di cui sopra non si adatta scenari in cui si vuole dire , eseguire un'operazione di database e gettare via la connessione ogni volta), ho trovato una soluzione relativamente decente che combina IoC con il modello Factory: Creare una classe che si assume la responsabilità di creare istanze di nuove istanze di un determinato tipo attraverso una funzione:

class MyObjectFactory: IMyObjectFactory 
{ 
    public MyObject CreateObject() 
    { 
     return new MyObject(); 
    } 
} 

Creare l'interfaccia per la classe di fabbrica MyObject:

public interface IMyObjectFactory 
{ 
    MyObject CreateObject(); 
} 

Poi configurare il contenitore IoC per fornire fabbrica a tutte le classi che usano le istanze di MyObject:

SimpleIoc.Default.Register<IMyObjectFactory, MyObjectFactory>(); 

Ora qualsiasi classe che richiede una nuova istanza di MyObject avrebbe dichiarato la sua esigenza MyObjectFactory (invece di MyObject requisito) nel costruttore per l'iniezione del costruttore:

public class MyObjectUser 
{ 
    MyObject _myObject; 
    public MyObjectUser(IMyObjectFactory factory) 
    { 
     _myObject = factory.CreateObject(); 
    } 
} 

in questo modo credo che non stai Bou per le limitazioni del modello Factory e per avere tutti i vantaggi dei contenitori IoC e dell'Iniezione del costruttore, aggirando anche la limitazione di SimpleIoC.

Problemi correlati