System.AddIn
La 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.org




14/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 problema

Le dipendenze statiche
il problema: le dipendenze statiche




             Componente                        Componente

             ComA                               ComB




14/03/2008                www.xedotnet.org                                  8
Il cammino verso la soluzione...




Componente    Interfaccia

ComA          IComB



              Componente

              ComB




 14/03/2008                 www.xedotnet.org                               9
Inversion of Control




                                                               Interfaccia
             Componente
                                   ServiceProvider             IComB
             ComA                       (IoC Container)




                                              Componente         IoC
                                              ComB              Config




14/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’s
Host                   Side                          Side                        AddIn
             View                                                View
                      Adapter                      Adapter




                                                         Dipendenza statica



14/03/2008                      www.xedotnet.org                                         19
Architettura: la simmetria




                                                     Isolation
                                                     Boundary




             Host/Add-In   View           Adapter    Contract




14/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 Argument



14/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 duplex

Demo: 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!

System.AddIn @ Xe.Net

  • 1.
    System.AddIn La via dell’estensibilitàsecondo il .NET framework » Mauro Servienti
  • 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.org 14/03/2008 www.xedotnet.org 2
  • 3.
    Upcoming Events Community Meeting In collaborazione con: 14/03/2008 www.xedotnet.org 3
  • 4.
    Perchè abbiamo bisognodi realizzare applicazioni estensibili. Estensibilità... who cares?
  • 5.
    Perchè? » Supporto perl’integrazione e l’interoperabilità; » Consente di modificare a caldo il comportamento; » È un’ottimo “strumento” commerciale; 14/03/2008 www.xedotnet.org 5
  • 6.
    Scrivere in otticaestensibilità » 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.
    Un primo approccioal problema Le dipendenze statiche
  • 8.
    il problema: ledipendenze statiche Componente Componente ComA ComB 14/03/2008 www.xedotnet.org 8
  • 9.
    Il cammino versola soluzione... Componente Interfaccia ComA IComB Componente ComB 14/03/2008 www.xedotnet.org 9
  • 10.
    Inversion of Control Interfaccia Componente ServiceProvider IComB ComA (IoC Container) Componente IoC ComB Config 14/03/2008 www.xedotnet.org 10
  • 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.
    Non avrai altrocontratto all’infuori di me. Un contratto è per sempre
  • 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.
    Problema: il versioningdel 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.
    Adesso che siamoinseparabili possiamo vivere felici? Finchè morte non ci separi
  • 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.
    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.
    La soluzione propostadal .NET framework System.AddIn: Architettura
  • 19.
    Architettura Dove eravamo… Host Contract AddIn Isolation Boundary Host AddIn Host’s Contract AddIn’s Host Side Side AddIn View View Adapter Adapter Dipendenza statica 14/03/2008 www.xedotnet.org 19
  • 20.
    Architettura: la simmetria Isolation Boundary Host/Add-In View Adapter Contract 14/03/2008 www.xedotnet.org 20
  • 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 Argument 14/03/2008 www.xedotnet.org 21
  • 22.
    La soluzione propostadal .NET framework System.AddIn: il codice
  • 23.
    Il contratto [AddInContract] public interfaceIMyContract: IContract { void Execute(); } 14/03/2008 www.xedotnet.org 23
  • 24.
    La vista sulcontratto » 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.
    Gli adattatori: AddInSide [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.
    Gli adattatori: HostSide [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.
    “ContractHandle” » Dato chel’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.
    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.
  • 30.
    E’ tutto chiaro,vero....?  Domande?
  • 31.
    P.S. Diario diBordo » “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.
    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.
    Gestione delle eccezioni:“unreliable tokens” Demo: Extreme SandBoxing
  • 34.
    Recap: a chepunto 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.
    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.
    Gestione degli eventie comunicazione duplex Demo: Pipeline Builder & Events Handling
  • 37.
    E’ tutto chiaro,vero....?  Domande?
  • 38.
    Il nostro rapportonon è più lo stesso... “cara ti amo” <cit.> Demo: Versioning
  • 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.
    Alcune note » Passaggiodi 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.
    Lo sconfinamento diun tipo complesso... Demo: ComplexType
  • 42.
    E’ tutto chiaro,vero....?  Domande?
  • 43.

Editor's Notes

  • #30  Demo: Creazione &quot;amanuense&quot; 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&apos;attributo [System.AddIn.Pipeline.AddInContract()] Aggiunta di un metodo impostazione dell&apos;output della build (..\\output\\contracts\\) Aggiungiamo un progetto per le &quot;Shared&quot; view impostiamo l&apos;output (..\\output\\AddInViews\\) aggiungiamo una interfaccia IMySampleContractView aggiungiamo le reference a System.AddIn marchiamo l&apos;interfaccia con [System.AddIn.Pipeline.AddInBaseAttribute()] Creiamo l&apos;adapter lato addin impostiamo l&apos;output su (..\\output\\AddInSideAdapters\\) Aggiungiamo le reference a System.AddIn Aggiungiamo le reference al contratto e alla view Aggiungiamo una classe per l&apos;adapter: IMySampleContractView_ViewToContract_AddInAdapter marchiamo la classe con l&apos;attributo [System.AddIn.Pipeline.AddInAdapterAttribute()] deriviamo da: : System.AddIn.Pipeline.ContractBase implementiamo l&apos;interfaccia del nostro contratto originale: AddIn.HandMade.Contract.IMySampleContract Aggiungiamo un costruttore che prenda in pasto la &quot;view&quot; (Shared in questo caso) e la salva in un field l&apos;implementazione dell&apos;interfaccia non farà altro che runculare la chiamata sulla view privata Creiamo il progetto per l&apos;addin aggiungiamo la classe per l&apos;addin aggiungiamo le reference a System.AddIn aggiungiamo la reference alle View (Shared) !!!!impostiamo copy local a false marchiamo l&apos;addin con: [System.AddIn.AddIn( &quot;NomeAddIn&quot; )] impostiamo l&apos;output su: ..\\output\\addins\\NomeAddIn\\ implementiamo l&apos;interfaccia della Shared View Creiamo l&apos;adattatore lato host impostiamo l&apos;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&apos;interfaccia della View creiamo l&apos;handle System.AddIn.Pipeline.ContractHandle passandogli una reference al contratto (che è poi il transparent proxy di remoting creiamo il progetto Console per l&apos;host aggiungiamo le reference a System.AddIn aggiungiamo la reference alla sharedview Aggiungiamo un po&apos; di codice: - list di backend IList&lt;IMySampleContractView&gt; addins = new List&lt;IMySampleContractView&gt;(); - ricerca e attivazione String[] result = AddInStore.Update( PipelineStoreLocation.ApplicationBase ); IList&lt;AddInToken&gt; tokens = AddInStore.FindAddIns( typeof( IMySampleContractView ), PipelineStoreLocation.ApplicationBase ); foreach( AddInToken token in tokens ) { addins.Add( token.Activate&lt;IMySampleContractView&gt;( AddInSecurityLevel.Internet ) ); } - invocazione foreach( IMySampleContractView addin in addins ) { addin.Execute(); } impostazione dell&apos;output: (..\\output\\) impostazione dello startup project breakpoint sull&apos;host e sull&apos;addint F5
  • #31  Demo: Creazione &quot;amanuense&quot; 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&apos;attributo [System.AddIn.Pipeline.AddInContract()] Aggiunta di un metodo impostazione dell&apos;output della build (..\\output\\contracts\\) Aggiungiamo un progetto per le &quot;Shared&quot; view impostiamo l&apos;output (..\\output\\AddInViews\\) aggiungiamo una interfaccia IMySampleContractView aggiungiamo le reference a System.AddIn marchiamo l&apos;interfaccia con [System.AddIn.Pipeline.AddInBaseAttribute()] Creiamo l&apos;adapter lato addin impostiamo l&apos;output su (..\\output\\AddInSideAdapters\\) Aggiungiamo le reference a System.AddIn Aggiungiamo le reference al contratto e alla view Aggiungiamo una classe per l&apos;adapter: IMySampleContractView_ViewToContract_AddInAdapter marchiamo la classe con l&apos;attributo [System.AddIn.Pipeline.AddInAdapterAttribute()] deriviamo da: : System.AddIn.Pipeline.ContractBase implementiamo l&apos;interfaccia del nostro contratto originale: AddIn.HandMade.Contract.IMySampleContract Aggiungiamo un costruttore che prenda in pasto la &quot;view&quot; (Shared in questo caso) e la salva in un field l&apos;implementazione dell&apos;interfaccia non farà altro che runculare la chiamata sulla view privata Creiamo il progetto per l&apos;addin aggiungiamo la classe per l&apos;addin aggiungiamo le reference a System.AddIn aggiungiamo la reference alle View (Shared) !!!!impostiamo copy local a false marchiamo l&apos;addin con: [System.AddIn.AddIn( &quot;NomeAddIn&quot; )] impostiamo l&apos;output su: ..\\output\\addins\\NomeAddIn\\ implementiamo l&apos;interfaccia della Shared View Creiamo l&apos;adattatore lato host impostiamo l&apos;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&apos;interfaccia della View creiamo l&apos;handle System.AddIn.Pipeline.ContractHandle passandogli una reference al contratto (che è poi il transparent proxy di remoting creiamo il progetto Console per l&apos;host aggiungiamo le reference a System.AddIn aggiungiamo la reference alla sharedview Aggiungiamo un po&apos; di codice: - list di backend IList&lt;IMySampleContractView&gt; addins = new List&lt;IMySampleContractView&gt;(); - ricerca e attivazione String[] result = AddInStore.Update( PipelineStoreLocation.ApplicationBase ); IList&lt;AddInToken&gt; tokens = AddInStore.FindAddIns( typeof( IMySampleContractView ), PipelineStoreLocation.ApplicationBase ); foreach( AddInToken token in tokens ) { addins.Add( token.Activate&lt;IMySampleContractView&gt;( AddInSecurityLevel.Internet ) ); } - invocazione foreach( IMySampleContractView addin in addins ) { addin.Execute(); } impostazione dell&apos;output: (..\\output\\) impostazione dello startup project breakpoint sull&apos;host e sull&apos;addint F5