Inversion of Control on the Phone: IPuzzleContainer
- lo stile che siamo abituati ad usare è efficace;
- il cambiamento ci obbliga ad essere meno efficaci;
Windows Phone 7
In questi giorni mi sto dilettando con lo sviluppo di un’applicazione per Windows Phone 7, è per uso personale e la sto facendo nel tempo libero sfruttando la cosa per studiare una piattaforma con cui avevo giochicchiato all’inizio e poi abbandonato per altri lidi . L’applicazione in se e per se non fa nulla di trascendentale e non è oggetto del post, l’intenzione è però quella di realizzarla seguendo lo stesso stile di programmazione che mi accompagna da anni nello sviluppo di applicazioni Wpf e Silverlight. In particolare quello che mi interessa in questo momento è:
- Model View ViewModel: con il solito approccio un po’ “talebano” finalizzato a spingermi al limite delle possibilità offerte dalla piattaforma;
- Inversion of Control e Dependency Injection: principalmente al fine di non perdere sane e buone abitudini e non ultimo al fine di poter introdurre con semplicità Unit Test su Windows Phone 7;
IPuzzleContainer
Al che mi sono detto: beh…facciamocelo , che ci vorrà mai
In effetti un paio d’ore di lavoro, più un’oretta di refactoring per renderlo molto simile a Castle Windsor nell’uso hanno prodotto questo:
Come si può notare la sintassi per la registrazione dei componenti è molto simile proprio a quella di Castle Windsor, in questo esempio ci limitiamo a registrare dei contratti e la loro implementazione concreta, nel primo caso abbiamo già una “live instance” e quindi registriamo quella. IMessageBroker ha una dipendenza (nel costruttore, quindi mandatory) proprio sui due tipi registrati in precedenza, IPuzzleContainer risolverà per noi le dipendenze all’atto della risoluzione del broker.var container = new PuzzleContainer(); container.Register ( EntryBuilder.For<Dispatcher>() .UsingInstance( Deployment.Current.Dispatcher ) ); container.Register ( EntryBuilder.For<IDispatcher>() .ImplementedBy<SilverlightDispatcher>() ); container.Register ( EntryBuilder.For<IMessageBroker>() .ImplementedBy<MessageBroker>() );
Naturalmente abbiamo anche il supporto per i tipi concreti e le factory:
LifecycleAwareService non implementa nessuna interfaccia e viene registrato direttamente, mentre nel secondo caso usiamo una factory per risolvere il tipo concreto.container.Register ( EntryBuilder.For<LifecycleAwareService>() ); container.Register ( EntryBuilder.For<IsolatedStorageSettings>().UsingFactory( () => { return IsolatedStorageSettings.ApplicationSettings; } ) );
Sempre per mantenermi allineato con Castle c’è anche il supporto per il Lifestyle che di default è Singleton, ma in fase di registrazione può essere cambiato a Transient, non c’è nessun supporto per altri tipi di Lifestyle e sinceramente non ne vedo la necessità. Se proprio fosse necessario si potrebbe ipotizzare un Threaded Lifestyle, cosa peraltro tutto tranne che difficile.
L’uso è altrettanto semplice:
Triviale direi. Un paio di note per concludere:var lifeSvc = container.Resolve<LifecycleAwareService>();
- Funziona? si;
- E’ affidabile: non ne ho la più pallida idea
- E’ performante: a naso sembrerebbe di si, ma non ho fatto la benché minima misurazione;
- Dove lo trovo? Radical for Windows Phone 7…
- Quando? a breve non ho ancora fatto check-in dei sorgenti, mi piacerebbe scrivere qualche Unit Test prima;
- Il prossimo step? il supporto per le facility sempre in stile Castle Windsor;
.m