Components are defined by tag <component/>
within <components/>
section.
<components>
<component ...attributes>
...elements
</component>
</components>
To register a component you need to specify at least two things - id of the component, and its type)
<components>
<component
id="notification"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
</component>
</components>
ℹ️ In Windsor 3 id
attribute is optional, so you need to only specify type
.
This is identical to specifying Component.For<EmailNotificationService>().Named("notification");
with Fluent Registration API.
More often you will want the component type to be an abstract base type, or interface, implemented by the type you're exposing
<components>
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
</component>
</components>
This is identical to specifying Component.For<INotificationService>().ImplementedBy<EmailNotificationService>().Named("notification");
.
It is possible to specify a lifestyle via the XML configuration
<components>
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm"
lifestyle="transient">
</component>
</components>
The list of valid values for the lifestyle
attribute (mapped to appropriate LifestyleManager
enum values):
Lifestyle | Notes |
---|---|
singleton |
This is the default lifestyle in Windsor |
thread |
|
transient |
Windsor keeps references to transient components! |
pooled |
Two additional attributes need to be defined: initialPoolSize and maxPoolSize both of which accept positive integer values |
scoped |
Optionally specifying the scopeAccessorType attribute |
bound |
|
custom |
For custom lifestyle additional attribute needs to be defined: customLifestyleType which points to the type implementing the lifestyle |
It is possible to specify parameters via XML configuration.
<components>
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm"
lifestyle="transient">
<parameters>
<smtpServer>localhost:667</smtpServer>
<senderEmail>#{admin.email}</senderEmail>
<emailFormatter>${emailFormatter}</emailFormatter>
</parameters>
</component>
</components>
As shown in the example parameters can be defined in three distinct ways:
In the above example smtpServer
is an inline parameter: its value - localhost:667, is provided right on the spot. Windsor's XML format lets you specify not just primitive types, but also lists, arrays, dictionaries or any other complex types. (read more)
In the above example senderEmail
is a property reference parameter: its value is defined in the <properties>
section of the configuration file (not shown here) under name admin.email
. You specify property references using #{property.id}
notation.
In the above example emailFormatter
is a service override parameter: as its value another component, registered with id equals emailFormatter
will be used. You specify service overrides using ${service.id}
notation.
Single component can be used as multiple services. This feature, called forwarded types in Windsor, is also exposed via XML.
<components>
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
<forwardedTypes>
<add service="Acme.Crm.Services.IEmailSender, Acme.Crm" />
</forwardedTypes>
</component>
</components>
By default when Windsor creates component it will try to set all its settable properties it can provide value for. When using XML configuration this behavior can be adjusted.
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm"
inspectionBehavior="none">
</component>
Inspection behavior | Notes |
---|---|
all | This is the default behavior |
none | Windsor will not try to set any properties |
declaredonly | Only properties declared on the component's type (and not ones declared on base types) will be set |
All power of underlying DynamicProxy library is exposed via XML configuration.
ℹ️ Read more: This guide only discusses the XML syntax. To learn more about how DynamicProxy works and how and where it can be helpful, read this tutorial.
Registering interceptors is very similar to service overrides:
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
<interceptors>
<interceptor>${loggingInterceptor}</interceptor>
</interceptors>
</component>
You reference interceptors via key, using standard reference notation.
You reference interceptor selector using selector
attribute on <interceptors>
element:
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
<interceptors selector="${interceptorsSelectorId}">
<interceptor>${loggingInterceptor}</interceptor>
</interceptors>
</component>
You reference proxy hook using hook
attribute on <interceptors>
element:
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
<interceptors hook="${proxyHookId}">
<interceptor>${loggingInterceptor}</interceptor>
</interceptors>
</component>
Windsor lets you mix your service with additional services into one object:
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
<mixins>
<mixin>${otherServiceId}</mixin>
</mixins>
</component>
You reference other services you want to mix in using Windsor's standard reference notation.
Windsor lets you specify additional interfaces to be implemented by your proxy. Implementation for these interfaces should be provided by interceptors:
<component
id="notification"
service="Acme.Crm.Services.INotificationService, Acme.Crm"
type="Acme.Crm.Services.EmailNotificationService, Acme.Crm">
<interceptors>
<interceptor>${metadataInterceptor}</interceptor>
</interceptors>
<additionalInterfaces>
<add interface="Acme.Crm.Services.IMetadataService, Acme.Crm" />
</additionalInterfaces>
</component>