Alkampfer's Place

Il blog di Gian Maria Ricci
posts - 659, comments - 871, trackbacks - 80

My Links

News

Gian Maria Ricci Mvp Logo CCSVI in Multiple Sclerosis

English Blog

Tag Cloud

Article Categories

Archives

Post Categories

Image Galleries

I miei siti

Siti utili

Castle Windsor - Facilities

Una delle caratteristiche più interessanti di Castle Windsor è l'estensibilità, ottenibile principalmente tramite le facilities, vediamo come costruirne una.

Caso pratico: Progetto che usa il pattern di Repository, avrò una ICustomerRepository, IORderRepository, in generale un repository per ogni root di ogni aggregato (Se seziono il dominio con gli aggregati [Evans DDD]) oppure un repository per ogni oggetto. LA cosa noiosa è avere nel file di configurazione di Castle Windsor una incredibile quantità di componenti configurati tutti eguali. Una possibile soluzione è creare una facility che scandisce tutti i tipi di un assembly, controlla la presenza di un attributo in base al quale aggiunge dinamicamente il componente nel contenitore. Come prima cosa si definisce un attributo custom.

[AttributeUsage(AttributeTargets.Interface, Inherited=true, AllowMultiple=false)] public class WindsorInterface : Attribute { public LifestyleType LifestyleType { get { return mLifestyleType; } set { mLifestyleType = value; } } private LifestyleType mLifestyleType = LifestyleType.Singleton; }

Fino a qui nulla di particolare un attributo con un unica proprietà che stabilisce il lifecycle, questo attributo va assegnato a tutte le interfacce per cui voglio fare autoscan, il passo successivo è creare una facilities che scandisca tutti i tipi di un assembly per configurare runtime un WindsorContainer.

public class AutoscanFacility : AbstractFacility { protected override void Init() { Configure(); } ...

Una facility è un particolare oggetto che si integra in un WindsorContainer per aggiungere caratteristiche, il primo passo è ereditare dalla AbstractFacility  e fare l'override del metodo Init() virtuale ed astratto. Nell'init semplicemente viene chiamata la funzione Configure(). Cio che rende castle molto semplice da configurare è l'astrazione che viene fatta sui parametri di configurazione, prima di andare avanti è doveroso mostrare ad esempio come configurare questa facility in un container.

<CastleWindsor> <facilities> <facility id="Facility.Autoscan" type="Nablasoft.Castle.Windsor.AutoscanFacility, NablaHelpers" > <assemblies> <assembly name="NablaHelpers.Tests" /> </assemblies> </facility> </facilities> </CastleWindsor>

Come si può vedere basta specificare la classe che implementa la faciliy e poi inserire tutti i parametri che si desidera, nel caso in esame una lista di assembly da esaminare. A questo punto vediamo come è fatta la funzione Configure

private void Configure() { foreach (IConfiguration child in FacilityConfig.Children) { if (child.Name == "assemblies") { ScanAssemblies(child); } else throw new ConfigurationErrorsException( "Unknown element " + child.Name + " in AutoscanFacility configuration"); } }

Accedere alla configurazione è banale, l'oggetto FacilityConfig presente nella classe base permette di esaminare la configurazione, per prima cosa si itera su tutti i nodi figli, come si vede dal frammento xml l'unico nodo che può essere specificato si chiama "assemblies".

private void ScanAssemblies(IConfiguration child) { foreach (IConfiguration asm in child.Children) { Assembly asmtoscan = Assembly.Load(asm.Attributes["name"]); ScanAssembly(asmtoscan); } }

La funzione scanAssemblies itera nuovamente su tutti i figli del nodo configurazione, in questo caso di valore "assembly" e per ogniuno di essi si recupera un riferimento all'assembly specificato, finalmente si chiama la funzione ScanAssembly().

private void ScanAssembly(Assembly asmtoscan) { foreach (Type t in asmtoscan.GetTypes()) { //Now scan all the interfaces implemented by the type. foreach (Type it in t.GetInterfaces()) { if (it.IsDefined(typeof(WindsorInterface), false)) { WindsorInterface wi = (WindsorInterface) System.Attribute.GetCustomAttribute(it, typeof (WindsorInterface)); Kernel.AddComponent(t.FullName, it, t, wi.LifestyleType); } } } }

Anche in questo caso il codice è decisamente semplice, per ogni tipo nell'assembly si controllano tutte le interfacce implementate e per ogniuna di esse si controlla se è definito l'attributo WindsorInterface, in caso positivo si recupera l'istanza dell'attributo per recuperare il LifeCycle, infine si aggiunge direttamente il componente runtime nell'oggetto Kernel che gestisce a basso livello le funzionalità di IoC.

Questo esempio mostra l'utilizzo base di una facilities, interagire con il kernel per aggiungere componenti a runtime.

Alk.

Print | posted on Wednesday, August 1, 2007 10:23 PM | Filed Under [ Castle ]

Feedback

Gravatar

# re: Castle Windsor - Facilities

Perchè evidentemente in nessuna istanza dell'attributo è stata mai specificata quella proprietà. :P

Alk.
9/3/2007 3:25 PM | Gian Maria
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET