Monday, July 27, 2009

Binsor 2.0 Spike

Recently, I tasked myself with the responsibility of spiking Binsor and checking if my current projects castle configuration (which we have in an XML config file) could be fully converted.

Binsor is a DSL language for Castle Windsor and is a feature offered in the reknowned open source Rhino.Commons assembly. There are quite a few "basic" posts about Binsor but there were a few configuration scenarios that I had to dig deeply for. This post attempts to describe these scenarios and also give an overall verdict of Binsor as a whole.


1. Import statements

You must import all assembly types in a Binsor file e.g.
import Billy.CommonLibraries
import Billy.Application.Facade from Billy.Application.Facade.RC2

Note that if you have a type with a namespace that is different to the assembly name e.g. all types under Billy.Application.Facade, you must specify in the format <namespace> from <assembly name>


2. Properties

Properties are simply represented via boo variable declaration e.g.
<properties>
<p1>00:02:00</p1>
<p2>SampleString</p2>
</properties>

would be represented as:

p1 = "00:02:00"
p2= "SampleString"

3. Comments


All comment lines start with '#' e.g.

# Properties

4. Facilities

Declaring facility usage is simple e.g.

<facility
id="factory_Support"
type="Castle.Facilities.FactorySupport.FactorySupportFacility, Castle.MicroKernel" />
would be represented as:

facility FactorySupportFacility



5. Components

The following component Billy.CommonTypes.Handler.Default

<component
id="exceptionHandler"
service="Billy.CommonTypes.IHandler, Billy.CommonTypes"
type="Billy.CommonTypes.Handler.Default, Billy.CommonTypes">
</component>
would be represented as:

component "exceptionHandler", Billy.CommonTypes.IHandler, Billy.CommonTypes.Handler.Default




6. Types instantiated using instance fields

The following component configuration for Billy.CommonTypes.SystemClock

<component
id="clock"
service="Billy.CommonTypes.IClock, Billy.CommonTypes"
type="Billy.CommonTypes.SystemClock, Billy.CommonTypes"
instance-accessor="Instance">
</component>
would be represented as:
component "clock", Billy.CommonTypes.IClock, Billy.CommonTypes.SystemClock: 
createUsing Instance



7. Components with parameters


<component
id="exceptionLogger"
service="Billy.CommonTypes.Exception.ILogger, Billy.CommonTypes"
type="Billy.CommonTypes.Exception.Logger.EventLog, Billy.CommonTypes">
<parameters>
<logName>#{exceptionLogName}</logName>
<source>#{exceptionLogSource}</source>
</parameters>
</component>
would be represented as:

component "exceptionHandler", Billy.CommonTypes.Exception.ILogger, Billy.CommonTypes.Exception.Logger.EventLog:
logName = exceptionLogName
source = exceptionLogSource



8. Components instantiated using factories


<component
id="sampleTypeInstantiatedWithFactory"
service="Billy.CommonTypes.IProviderFactory, Billy.CommonTypes"
type="Billy.CommonTypes.ProviderFactory, Billy.CommonTypes"
factoryId="mySampleFactory"
factoryCreate="GetSampleType">
</component>
would be represented as:

component "sampleTypeInstantiatedWithFactory", Billy.CommonTypes.IProviderFactory, Billy.CommonTypes.ProviderFactory"
createUsing @mySampleFactory.GetSampleType



9. Event wiring


<component
id="eventingBroker"
service="Billy.CommonTypes.Eventing.IBroker, Billy.CommonTypes"
type="Billy.CommonTypes.Eventing.Broker, Billy.CommonTypes">
<subscribers>
<subscriber
id="subscriber1"
event="Event1"
handler="OnEvent1Firing" />
<subscriber
id="subscriber2"
event="Event2"
handler="OnEvent2Firing" />
</subscribers>
</component>
would be represented as:

component "eventingBroker", Billy.CommonTypes.Eventing.IBroker, Billy.CommonTypes.Eventing.Broker:
wireEvent Event1:
to @subscriber1.OnEvent1Firing
wireEvent Event2:
to @subscriber2.OnEvent2Firing



10. Startable components


<component
id="myStartableComponent"
type="Billy.CommonTypes.Type1, Billy.CommonTypes"
startable="true">
</component>
would be represented as:

component "myStartableComponent", Billy.CommonTypes.Type1:
@startable = true



11. Transient components


<component
id="myTransientComponent"
type="Billy.CommonTypes.Type2, Billy.CommonTypes"
lifestyle="transient">
</component>
would be represented as:

component "myTransientComponent", Billy.CommonTypes.Type2:
lifestyle Transient



12. WCF client components


<component
id="myWCFClient"
type="Billy.Clients.IClient, Billy.Clients"
wcfEndpointConfiguration="MyClient">
</component>
would be represented as:

component "myWCFClient", Billy.Clients.IClient:
wcfEndpointConfiguration="MyClient"

Conclusion


Excellent overall as it reduced the size of my castle configuration file down to 38% of its original size. The Binsor file is also much more readable and eradicates all the XML fluff! However the downside is that I had to reference the Rhino.Commons assembly. Binsor may get integrated into Castle in a future release so I am nearly more inclined to wait until this happens!

A big thank you to Craig Neuwirt for answering any Binsor questions that I had (via Castle forum)

No comments:

Post a Comment