System.AddIn @ Xe.Net
Upcoming SlideShare
Loading in...5
×
 

System.AddIn @ Xe.Net

on

  • 335 views

System.AddIn @ Xe.Net

System.AddIn @ Xe.Net

Statistics

Views

Total Views
335
Views on SlideShare
335
Embed Views
0

Actions

Likes
0
Downloads
3
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 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 addins = new List(); - ricerca e attivazione String[] result = AddInStore.Update( PipelineStoreLocation.ApplicationBase ); IList tokens = AddInStore.FindAddIns( typeof( IMySampleContractView ), PipelineStoreLocation.ApplicationBase ); foreach( AddInToken token in tokens ) { addins.Add( token.Activate( 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 addins = new List(); - ricerca e attivazione String[] result = AddInStore.Update( PipelineStoreLocation.ApplicationBase ); IList tokens = AddInStore.FindAddIns( typeof( IMySampleContractView ), PipelineStoreLocation.ApplicationBase ); foreach( AddInToken token in tokens ) { addins.Add( token.Activate( 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 System.AddIn @ Xe.Net Presentation Transcript

  • System.AddInLa via dell’estensibilità secondo il .NET framework » Mauro Servienti
  • 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
  • Upcoming Events Community Meeting In collaborazione con:14/03/2008 www.xedotnet.org 3
  • Perchè abbiamo bisogno di realizzare applicazioni estensibili. Estensibilità... who cares?
  • 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
  • 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
  • Un primo approccio al problemaLe dipendenze statiche
  • il problema: le dipendenze statiche Componente Componente ComA ComB14/03/2008 www.xedotnet.org 8
  • Il cammino verso la soluzione...Componente InterfacciaComA IComB Componente ComB 14/03/2008 www.xedotnet.org 9
  • Inversion of Control Interfaccia Componente ServiceProvider IComB ComA (IoC Container) Componente IoC ComB Config14/03/2008 www.xedotnet.org 10
  • 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
  • Non avrai altro contratto all’infuori di me. Un contratto è per sempre
  • Problema: le dipendenze» Entrambe le parti dipendono in maniera statica dal contratto; Host Contract AddIn Dipendenza Statica 14/03/2008 www.xedotnet.org 13
  • 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
  • Adesso che siamo inseparabili possiamo vivere felici? Finchè morte non ci separi
  • 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
  • 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
  • La soluzione proposta dal .NET framework System.AddIn: Architettura
  • 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
  • Architettura: la simmetria Isolation Boundary Host/Add-In View Adapter Contract14/03/2008 www.xedotnet.org 20
  • 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
  • La soluzione proposta dal .NET framework System.AddIn: il codice
  • Il contratto[AddInContract]public interface IMyContract: IContract{ void Execute();}14/03/2008 www.xedotnet.org 23
  • 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
  • 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
  • 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
  • “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
  • 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
  • Ci proviamo?Demo: HandMade Solution
  • E’ tutto chiaro, vero....?  Domande?
  • 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
  • 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
  • Gestione delle eccezioni: “unreliable tokens” Demo: Extreme SandBoxing
  • 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;
  • 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
  • Gestione degli eventi e comunicazione duplexDemo: Pipeline Builder & Events Handling
  • E’ tutto chiaro, vero....?  Domande?
  • Il nostro rapporto non è più lo stesso... “cara ti amo” <cit.> Demo: Versioning
  • 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”;
  • 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>;
  • Lo sconfinamento di un tipo complesso... Demo: ComplexType
  • E’ tutto chiaro, vero....?  Domande?
  • Si mangia!  Grazie!