Introduction
Customer Contact Manager is a simple sample application showcasing usage of Castle Windsor in Silverlight. This page will walk you through all the features of Windsor used by the application. You can download the code
here.
Version
The application uses Silverlight 4 and Windsor 2.5. If you want to download the entire source code, it uses Visual Studio 2010 solution.
Bootstrapping - the guywire
The application uses a dedicated class, called
GuyWire to implement the
Three Container calls pattern. It does so via the following three methods:
Guywire pattern
To read more about the guywire pattern see
this and
this blogpost.
Container set up - installers

Installers folder in the solution
The application uses
Windsor Installers to encapsulate code responsible for registering components with the container. Each group of the components has dedicated installer type. All installers are contained in a dedicated project folder/namespace to cleanly separate them from the rest of the application.
For demonstration purposes each installer uses different pieces of API available to register the components.
BehaviorsInstaller
Behaviors in the application are classes extending our model with additional capabilities. They are implemented as
DynamicProxy Interceptors.
container.Register(AllTypes.FromThisAssembly().BasedOn<IInterceptor>());
CommandInstaller¶
Command installer installs commands which handle interactions with the user. Commands use
attributed registration.
container.Register(AllTypes.FromThisAssembly()
.Where(t => t.Namespace.EndsWith("Commands") &&
Component.IsCastleComponent(t)));ModelInstaller
Model Installer registers model objects in our application (due to extreme simplicity of the app there's just one such class -
Customer).
container.Register(AllTypes.FromThisAssembly()
.Where(Component.IsInSameNamespaceAs<Customer>())
.Configure(c => c.LifeStyle.Transient
.Proxy.AdditionalInterfaces(typeof (IEditableObject),
typeof (INotifyPropertyChanged))
.Interceptors(typeof (EditableBehavior),
typeof (NotifyPropertyChangedBehavior)))
.ConfigureFor<Customer>(c => c.DynamicParameters(
(k, @params) => @params.Insert(DateTime.Now))));That's the most complicated installer in the application and there's quite a lot of stuff happening here so let's go over each step in turn
- line 3 - In addition to filtering (selecting which types to register and relying on defaults like in previous installers) we explicitly specify a non-default lifestyle.
- line 4 and 5 - Additionally we specify two interfaces we want our model objects to implement -
IEditableObjects and INotifyPropertyChanged. These are Silverlight interfaces that will give our model objects editability and notifications to/from the UI of changes property values. - line 6 and 7 - To provide implementation for the interfaces we specify interceptors that will handle the task.
- lines 8 and 9 - in addition to above configuration that will be applied to all components matched by the filtering conditions, we specify additional fine-grained configuration just for
Customer class - we specify typed Dynamic parameter for DateTime (we'll discuss why we do that when we cover CustomersFactory below).
ServiceInstaller
Service installer registers application services. We have three of these -
ICustomerRepository,
IModelFactory and
CustomerFactory delegate which is registered implicitly.
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ICustomerRepository>()
.ImplementedBy<CustomerRepository>()
.DependsOn(Property.ForKey("serviceUri")
.Eq("Fake service Uri for fake repository, but you get the idea")),
Component.For<IModelFactory>()
.AsFactory());We register
Typed Factory Facility, so that we can use
IModelFactory and
CustomerFactory delegate as typed factories (
interface-based and
delegate-based respectively)
In addition we register
static named dependency for customer repository - serviceUri. In real application that would be address of our backend service. In .NET app we could pass connection string like this.
ViewInstaller
View installer registers views in our application based on namespace
container.Register(AllTypes.FromThisAssembly()
.Where(Component.IsInNamespace("Castle.Samples.WindsorSilverlight.Views")));