BlogServiceHost.Create()

WCF & Azure - Il blog di Fabio Cozzolino

Recent Posts

Tags

My

Twitter

Community

Archives

Email Notifications

Social Bar Widget

Inversion of Control con WCF e Unity (Parte III)

Dalle puntate precedenti:

Abbiamo visto come poter sviluppare un semplice sistema diIoC con WCF sfruttando Unity. La stessa logica è in realtà applicabile a tutti gli altri framework .NET che forniscono funzionalità di IoC.

Vorrei però arricchire quanto già detto per consentire di sfruttare lo UnityServiceBehavior anche in situazioni in cui tutte le impostazioni vengono gestite direttamente dal file di configurazione, e non da codice come abbiamo precedentemente visto.

Per ottenere questo risultato abbiamo bisogno di sviluppare una particolare estenzione, una classe che eredita dal BehaviorExtensionElement. Sviluppiamo quindi il nostro UnityServiceBehaviorExtensionElement.

  1: public class UnityServiceBehaviorExtensionElement : BehaviorExtensionElement
  2: {
  3:     [ConfigurationProperty("containerName")]
  4:     public string ContainerName
  5:     {
  6:         get
  7:         {
  8:             return (string) base["containerName"];
  9:         }
 10:     }
 11: 
 12:     protected override object CreateBehavior()
 13:     {
 14:         return new UnityServiceBehavior(this.ContainerName);
 15:     }
 16: 
 17:     public override Type BehaviorType
 18:     {
 19:         get { return typeof(UnityServiceBehavior); }
 20:     }
 21: }

La classe dichiara semplicemente due metodi: il primo restituisce l’istanza del behavior, mentre il secondo identifica il tipo di behavior che stiamo costruendo. Nella creazione dell’istanza dell’UnityServiceBehavior viene passato il valore della proprietà ContainerName che contiene il nome della sezione di configurazione relativa al container che vogliamo utilizzare.

Immaginiamo di avere questa configurazione di Unity:

  1: <unity>
  2: 
  3:   <containers>
  4: 
  5:     <container name="BookServiceContainer">
  6:       <types>
  7: 
  8:         <type type="DotNetSide.WCF.IoC.Service.InnerBookService, DotNetSide.WCF.IoC.Service"
  9:               name="inner"/>
 10: 
 11:         <type type="DotNetSide.WCF.IoC.Service.IBookService, DotNetSide.WCF.IoC.Service"
 12:               mapTo="DotNetSide.WCF.IoC.Service.BookService, DotNetSide.WCF.IoC.Service">
 13:           <typeConfig>
 14:             <constructor>
 15:               <param name="innerService" parameterType="DotNetSide.WCF.IoC.Service.InnerBookService, DotNetSide.WCF.IoC.Service">
 16:                 <dependency name="inner" />
 17:               </param>
 18:             </constructor>
 19:           </typeConfig>
 20:         </type>
 21: 
 22:       </types>
 23:     </container>
 24: 
 25:   </containers>
 26: 
 27: </unity>
 28: 

La proprietà ContainerName dovrà riportare il nome BookServiceContainer. Prima di utilizzare lo UnityServiceBehaviorExtensionElement, creiamo il costruttore dello UnityServiceBehavior che accetta come parametro il nome del container:

  1: public UnityServiceBehavior(string containerName)
  2:     : this(GetContainer(containerName))
  3: {
  4: }
  5: 
  6: private static IUnityContainer GetContainer(string containerName)
  7: {
  8:     IUnityContainer unityContainer = null;
  9:     var configurationSection =
 10:         (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
 11: 
 12:     UnityContainerElement unityContainerElement = null;
 13:     if (!string.IsNullOrEmpty(containerName))
 14:     {
 15:         unityContainerElement = configurationSection.Containers[containerName];
 16:     }
 17: 
 18:     if (unityContainerElement == null)
 19:     {
 20:         unityContainerElement =
 21:             configurationSection.Containers.Default;
 22:     }
 23: 
 24:     unityContainer = new UnityContainer();
 25:     unityContainerElement.Configure(unityContainer);
 26: 
 27:     return unityContainer;
 28: }

Il costruttore invoca il metodo privato GetContainer per ottenere l’istanza del container e successivamente chiama il costruttore che accetta il container come parametro passando, appunto, l’istanza appena ottenuta.

Ora possiamo utilizzare la nostra estensione nel file di configurazione. Aggiungiamo un nuovo elemento nella sezione extensions del system.serviceModel:

  1: <system.serviceModel>
  2:   ...
  3:   <extensions>
  4:     <behaviorExtensions>
  5:       <add name="unityService"
  6:            type="DotNetSide.WCF.IoC.Unity.UnityServiceBehaviorExtensionElement, DotNetSide.WCF.IoC.Unity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  7:     </behaviorExtensions>
  8:   </extensions>
  9:   ...
 10: </system.serviceModel>

Inseriamo quindi la configurazione del behavior:

  1: <system.serviceModel>
  2:   ...
  3:   <behaviors>
  4:     <serviceBehaviors>
  5:       <behavior name="DotNetSide.WCF.IoC.Service.BookServiceBehavior">
  6:         <serviceMetadata httpGetEnabled="true"/>
  7:         <serviceDebug includeExceptionDetailInFaults="false"/>
  8:         <unityService containerName="BookServiceContainer" />
  9:       </behavior>
 10:     </serviceBehaviors>
 11:   </behaviors>
 12:   ...
 13: </system.serviceModel>

Ora possiamo creare semplicemente il nostro ServiceHost (non lo UnityServiceHost) ed utilizzarlo normalmente. Questo utilizzo di pone anche come alternativa a quanto visto nella seconda parte (Inversion of Control con WCF e Unity (Parte II)) perchè in questo modo non è più necessario utilizzare il ServiceHostFactory per istanziare il ServiceHost.

Se avete dubbi, chiedete pure …

bye

Posted: Mar 28 2009, 09:25 PM by Fabio.Cozzolino | with no comments
Filed under: , ,