Welcome Guest, you are in: Login

Castle Project

RSS RSS

Navigation (Windsor)






Search the wiki
»

PoweredBy

This documentation is a work in progress.

Let us know if some information is not clear, inaccurate or missing. Also feel free to update the wiki yourself.

Silverlight Sample App Customers Contact Manager

RSS
Modified on 2011/01/24 06:43 by Jan Wilson Categorized as Samples

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. Main screen
Image
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:
  • Wire which installs all the components using auto-discovery of Installers.
    container.Install(FromAssembly.This());


  • GetRoot which obtains the root object of the application.
    return container.Resolve<MainView>();


  • Dewire which tears down the container
    if (container == null) return;
    
    container.Dispose();
    container = null;


Image
Guywire pattern

To read more about the guywire pattern see this and this blogpost.



Container set up - installers

Installers folder in the solution

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")));

ScrewTurn Wiki version 3.0.4.560. Some of the icons created by FamFamFam.