System.AddIn @ Xe.Net

344 views

Published on

System.AddIn @ Xe.Net

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
344
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • Demo: Creazione "amanuense" Crea la solution vuota Creazione del progetto dei contratti aggiunta del contratto aggiunta delle reference a System.AddIn fagli notare che sono compilati per la 2.0 inheritance da IContract marcatura con l'attributo [System.AddIn.Pipeline.AddInContract()] Aggiunta di un metodo impostazione dell'output della build (..\\output\\contracts\\) Aggiungiamo un progetto per le "Shared" view impostiamo l'output (..\\output\\AddInViews\\) aggiungiamo una interfaccia IMySampleContractView aggiungiamo le reference a System.AddIn marchiamo l'interfaccia con [System.AddIn.Pipeline.AddInBaseAttribute()] Creiamo l'adapter lato addin impostiamo l'output su (..\\output\\AddInSideAdapters\\) Aggiungiamo le reference a System.AddIn Aggiungiamo le reference al contratto e alla view Aggiungiamo una classe per l'adapter: IMySampleContractView_ViewToContract_AddInAdapter marchiamo la classe con l'attributo [System.AddIn.Pipeline.AddInAdapterAttribute()] deriviamo da: : System.AddIn.Pipeline.ContractBase implementiamo l'interfaccia del nostro contratto originale: AddIn.HandMade.Contract.IMySampleContract Aggiungiamo un costruttore che prenda in pasto la "view" (Shared in questo caso) e la salva in un field l'implementazione dell'interfaccia non farà altro che runculare la chiamata sulla view privata Creiamo il progetto per l'addin aggiungiamo la classe per l'addin aggiungiamo le reference a System.AddIn aggiungiamo la reference alle View (Shared) !!!!impostiamo copy local a false marchiamo l'addin con: [System.AddIn.AddIn( "NomeAddIn" )] impostiamo l'output su: ..\\output\\addins\\NomeAddIn\\ implementiamo l'interfaccia della Shared View Creiamo l'adattatore lato host impostiamo l'output su: (..\\output\\HostSideAdapters\\) aggiungiamo le reference a System.AddIn Aggiungiamo le reference al contratto e alla view creiamo la classe per adattare dal contratto alla view: IMySampleContract_ContractToView_HostAdapter marchiamo con [System.AddIn.Pipeline.HostAdapterAttribute()] aggiungiamo un costruttore che prende una reference al contratto e lo adatta alla view implementiamo l'interfaccia della View creiamo l'handle System.AddIn.Pipeline.ContractHandle passandogli una reference al contratto (che è poi il transparent proxy di remoting creiamo il progetto Console per l'host aggiungiamo le reference a System.AddIn aggiungiamo la reference alla sharedview Aggiungiamo un po' di codice: - list di backend IList<IMySampleContractView> addins = new List<IMySampleContractView>(); - ricerca e attivazione String[] result = AddInStore.Update( PipelineStoreLocation.ApplicationBase ); IList<AddInToken> tokens = AddInStore.FindAddIns( typeof( IMySampleContractView ), PipelineStoreLocation.ApplicationBase ); foreach( AddInToken token in tokens ) { addins.Add( token.Activate<IMySampleContractView>( AddInSecurityLevel.Internet ) ); } - invocazione foreach( IMySampleContractView addin in addins ) { addin.Execute(); } impostazione dell'output: (..\\output\\) impostazione dello startup project breakpoint sull'host e sull'addint F5
  • Demo: Creazione "amanuense" Crea la solution vuota Creazione del progetto dei contratti aggiunta del contratto aggiunta delle reference a System.AddIn fagli notare che sono compilati per la 2.0 inheritance da IContract marcatura con l'attributo [System.AddIn.Pipeline.AddInContract()] Aggiunta di un metodo impostazione dell'output della build (..\\output\\contracts\\) Aggiungiamo un progetto per le "Shared" view impostiamo l'output (..\\output\\AddInViews\\) aggiungiamo una interfaccia IMySampleContractView aggiungiamo le reference a System.AddIn marchiamo l'interfaccia con [System.AddIn.Pipeline.AddInBaseAttribute()] Creiamo l'adapter lato addin impostiamo l'output su (..\\output\\AddInSideAdapters\\) Aggiungiamo le reference a System.AddIn Aggiungiamo le reference al contratto e alla view Aggiungiamo una classe per l'adapter: IMySampleContractView_ViewToContract_AddInAdapter marchiamo la classe con l'attributo [System.AddIn.Pipeline.AddInAdapterAttribute()] deriviamo da: : System.AddIn.Pipeline.ContractBase implementiamo l'interfaccia del nostro contratto originale: AddIn.HandMade.Contract.IMySampleContract Aggiungiamo un costruttore che prenda in pasto la "view" (Shared in questo caso) e la salva in un field l'implementazione dell'interfaccia non farà altro che runculare la chiamata sulla view privata Creiamo il progetto per l'addin aggiungiamo la classe per l'addin aggiungiamo le reference a System.AddIn aggiungiamo la reference alle View (Shared) !!!!impostiamo copy local a false marchiamo l'addin con: [System.AddIn.AddIn( "NomeAddIn" )] impostiamo l'output su: ..\\output\\addins\\NomeAddIn\\ implementiamo l'interfaccia della Shared View Creiamo l'adattatore lato host impostiamo l'output su: (..\\output\\HostSideAdapters\\) aggiungiamo le reference a System.AddIn Aggiungiamo le reference al contratto e alla view creiamo la classe per adattare dal contratto alla view: IMySampleContract_ContractToView_HostAdapter marchiamo con [System.AddIn.Pipeline.HostAdapterAttribute()] aggiungiamo un costruttore che prende una reference al contratto e lo adatta alla view implementiamo l'interfaccia della View creiamo l'handle System.AddIn.Pipeline.ContractHandle passandogli una reference al contratto (che è poi il transparent proxy di remoting creiamo il progetto Console per l'host aggiungiamo le reference a System.AddIn aggiungiamo la reference alla sharedview Aggiungiamo un po' di codice: - list di backend IList<IMySampleContractView> addins = new List<IMySampleContractView>(); - ricerca e attivazione String[] result = AddInStore.Update( PipelineStoreLocation.ApplicationBase ); IList<AddInToken> tokens = AddInStore.FindAddIns( typeof( IMySampleContractView ), PipelineStoreLocation.ApplicationBase ); foreach( AddInToken token in tokens ) { addins.Add( token.Activate<IMySampleContractView>( AddInSecurityLevel.Internet ) ); } - invocazione foreach( IMySampleContractView addin in addins ) { addin.Execute(); } impostazione dell'output: (..\\output\\) impostazione dello startup project breakpoint sull'host e sull'addint F5
  • System.AddIn @ Xe.Net

    1. 1. System.AddInLa via dell’estensibilità secondo il .NET framework » Mauro Servienti
    2. 2. Who I am... Mauro Servienti blog: http://blogs.ugidotnet.org/topics email: mauro@topics.it web: https://mvp.support.microsoft.com/profile/mauro community: www.xedotnet.org, www.ugidotnet.org14/03/2008 www.xedotnet.org 2
    3. 3. Upcoming Events Community Meeting In collaborazione con:14/03/2008 www.xedotnet.org 3
    4. 4. Perchè abbiamo bisogno di realizzare applicazioni estensibili. Estensibilità... who cares?
    5. 5. Perchè?» Supporto per l’integrazione e l’interoperabilità;» Consente di modificare a caldo il comportamento;» È un’ottimo “strumento” commerciale; 14/03/2008 www.xedotnet.org 5
    6. 6. Scrivere in ottica estensibilità» Pensare agli entry point;» Prevedere quali dati potranno essere necessari;» Incapsulare i dati in classi adatte al loro trasporto: • EventArgs; • CancelEventArgs; • CustomEventArgs : CancelEventArgs/EventArgs» Le “pipeline”, un esempio da seguire: • HttpModule + HttpHanlder; 14/03/2008 www.xedotnet.org 6
    7. 7. Un primo approccio al problemaLe dipendenze statiche
    8. 8. il problema: le dipendenze statiche Componente Componente ComA ComB14/03/2008 www.xedotnet.org 8
    9. 9. Il cammino verso la soluzione...Componente InterfacciaComA IComB Componente ComB 14/03/2008 www.xedotnet.org 9
    10. 10. Inversion of Control Interfaccia Componente ServiceProvider IComB ComA (IoC Container) Componente IoC ComB Config14/03/2008 www.xedotnet.org 10
    11. 11. Inversion of Control» Elevato supporto per la manutenzione» Sostituzione dei componenti a caldo» Supporto esteso per l’estensibilità: • Intercepting; • Dependency Injection • Chain of Responsability» Ma... IoC si basa sul contratto;»  Nonostante tutto adoro IoC! 14/03/2008 www.xedotnet.org 11
    12. 12. Non avrai altro contratto all’infuori di me. Un contratto è per sempre
    13. 13. Problema: le dipendenze» Entrambe le parti dipendono in maniera statica dal contratto; Host Contract AddIn Dipendenza Statica 14/03/2008 www.xedotnet.org 13
    14. 14. Problema: il versioning del contratto» Un contratto in quanto tale non dovrebbe cambiare nel tempo;» Sappiamo che nella vita reale questo non è sempre vero: • Analisi iniziale sbagliata; • Condizioni che cambiano; • Introduzione di nuove funzionalità che non potevano essere previste; • Nuova versione dell’applicazione che vuole soddisfare nuovi requisiti; • Etc... 14/03/2008 www.xedotnet.org 14
    15. 15. Adesso che siamo inseparabili possiamo vivere felici? Finchè morte non ci separi
    16. 16. Il versioning non è l’unico dei problemi» Il processo di Discovery;» L’attivazione degli AddIn; • Le dipendenze, da library di terze parti, sia dell’Host che dell’AddIn: the AssemblyResolve problem;» L’isolamento del codice altrui: Sandboxing; • La gestione della security; • Gestione degli errori nell’AddIn: • Il fx 2.0 ha cambiato il comportamento in caso eccezione non gestita;» La gestione del ciclo di vita: Unloading; 14/03/2008 www.xedotnet.org 16
    17. 17. Ma non solo...» Compatibilità all’indietro: • Nuovi Host che hanno bisogno di caricare vecchi AddIn;» Compatibilità in avanti: • Vecchi Host che hanno bisogno di funzionalità fornite da nuovi AddIn;» La necessità di introdurre nuovi livelli di isolamento: • In Process; • Different AppDomain; • Out of Process; 14/03/2008 www.xedotnet.org 17
    18. 18. La soluzione proposta dal .NET framework System.AddIn: Architettura
    19. 19. Architettura Dove eravamo… Host Contract AddIn Isolation Boundary Host AddIn Host’s Contract AddIn’sHost Side Side AddIn View View Adapter Adapter Dipendenza statica14/03/2008 www.xedotnet.org 19
    20. 20. Architettura: la simmetria Isolation Boundary Host/Add-In View Adapter Contract14/03/2008 www.xedotnet.org 20
    21. 21. Architettura: l’attivazione Isolation Boundary Host’s AddIn View Host IContract AddIn Base Host AddIn Of Adapter Adapter (AddIn view AddIn of contract) Inherits/Implements Constructor Argument14/03/2008 www.xedotnet.org 21
    22. 22. La soluzione proposta dal .NET framework System.AddIn: il codice
    23. 23. Il contratto[AddInContract]public interface IMyContract: IContract{ void Execute();}14/03/2008 www.xedotnet.org 23
    24. 24. La vista sul contratto» Host View: public interface IMyContractView { void Execute(); }» AddIn View: [AddInBase] public interface IMyContractView { void Execute(); }» Le View possono essere “SharedViews”;14/03/2008 www.xedotnet.org 24
    25. 25. Gli adattatori: AddIn Side[AddInAdapter]public class MyAddInSideAdapter: ContractBase, IMyContract{ IMyContractView _contract; public MyAddInSideAdapter( IMyContractView contract ) { _contract = contract; } public void Execute() { _contract.Execute(); }}14/03/2008 www.xedotnet.org 25
    26. 26. Gli adattatori: Host Side[HostAdapter]public class MyHostSideAdapter : IMyContractView{ IMyContract _contract; ContractHandle _handle; public MyHostSideAdapter( IMyContract contract ) { _contract = contract; _handle = new ContractHandle(contract); } public void Execute() { _contract.Execute(); }}14/03/2008 www.xedotnet.org 26
    27. 27. “ContractHandle”» Dato che l’architettura permette agli AddIn di comunicare attraverso i confini di un AppDomain (o addirittura di un processo) non possiamo fare affidamento sul GC per la gestione della memoria.» Questa classe ci offre un sistema di “reference counting” COM Like: • Quando viene costruito un ContractHandle nel costruttore viene chiamato AcquireLifetimeToken(). • Quando il ContractHandle viene “disposto” viene chiamato RevokeLifetimeToken(). 14/03/2008 www.xedotnet.org 27
    28. 28. Install  Find  Activate  Unload» Install: AddInStore.Update( path );» Find: IList<AddInToken> tokens = AddInStore.FindAddIns( typeof( IMyContractView ),path );» Activate: IMyAddIn addIn = token.Activate( AddInSecurityLevel.Internet );» Unload: AddInController c = AddInController.GetAddInController( addin ); c.Shutdown(); 14/03/2008 www.xedotnet.org 28
    29. 29. Ci proviamo?Demo: HandMade Solution
    30. 30. E’ tutto chiaro, vero....?  Domande?
    31. 31. P.S. Diario di Bordo» “Folder Naming”: quello è e quello deve essere, siamo in V1...;» L’AddIn può intercettare il suo shutdown: • Evento custom esposto dall’host; • Distruttore: C# Finalizer • AppDomain.UnloadDomain • Attenzione alla CAS: PermissionSet permSet = new PermissionSet( PermissionState.None ); permSet.AddPermission( new SecurityPermission( SecurityPermissionFlag.ControlAppDomain | SecurityPermissionFlag.Execution ) ); 14/03/2008 www.xedotnet.org 31
    32. 32. P.S. Extreme Sandboxing» È possibile attivare gli AddIn in un processo separato: • Fornisce massimo supporto per il sandboxing • Isola il processo host dalle eventuali exception non gestite dall’AddIn: • Il CLR del fx 2.0 introduce un radicale cambiamento; • È possibile, ma non consigliabile, cambiare questo comportamento (via app.config): • configurationruntimelegacyUnhandledExceptionPolicy enabled="1“» Se usate un processo separato eseguite l’attach anche di quello per poter debuggare; 14/03/2008 www.xedotnet.org 32
    33. 33. Gestione delle eccezioni: “unreliable tokens” Demo: Extreme SandBoxing
    34. 34. Recap: a che punto siamo...» Ogni AddIn vive, su disco, nella sua cartella: • Con le sue dipendenze; • Senza generare conflitti di versione con gli altri AddIn; • Con Il proprio faile di configurazione.» L’host può intercettare gli errori in un AddIn, scaricarlo ed eventualmente ricaricarlo senza che questo impatti sull’host e sugli altri AddIn; • A patto che non giri in un processo separato;» Gli AddIn possono essere isolati (Sandboxing) fornendo un particolare contesto di security;» Gli AddIn possono essere scaricati liberando risorse;
    35. 35. Tutto bello ma... quanto codice» Abbiamo scritto troppo plumbing code per ottenere il risultato desiderato: • Pipeline Builder Tool: • Genera tutto il plumbing code in maniera automatica; • Pipeline Hint: • Ci permette di controllare il Pipeline Builder Tool: • SharedView; • Commenti; • Naming degli Assembly generati; • Fornisce supporto per esporre eventi tra Host e AddIn e viceversa;14/03/2008 www.xedotnet.org 35
    36. 36. Gestione degli eventi e comunicazione duplexDemo: Pipeline Builder & Events Handling
    37. 37. E’ tutto chiaro, vero....?  Domande?
    38. 38. Il nostro rapporto non è più lo stesso... “cara ti amo” <cit.> Demo: Versioning
    39. 39. Recap: data astrale....» Cuore della gestione del versioning sono gli adattatori;» Tutto può essere soggetto a versioning: • Contratto degli AddIn; • Contratto dell’Host; • Contratto dei “dati”;» Il Pipeline Builder Tool genera adattatori per tutto ciò che implementa, nell’assembly del contratto l’interfaccia, “IContract”;
    40. 40. Alcune note» Passaggio di un tipo complesso attraverso i confini: • Abbiamo a che fare con remoting: • Il tipo deve essere serializzabile? • Chi è che affettivamente passa i confini? • Definire sempre un’interfaccia; • Se dobbiamo passare una collection, nel contratto, usiamo IListContract<T>: • La classe statica CollectionAdapters vi offre facilities per la conversione da e verso IList<T>;
    41. 41. Lo sconfinamento di un tipo complesso... Demo: ComplexType
    42. 42. E’ tutto chiaro, vero....?  Domande?
    43. 43. Si mangia!  Grazie!

    ×