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.

Startable Facility

RSS
Modified on 2012/11/22 21:55 by Krzysztof Koźmic Categorized as API, Extensions, Facilities

Introduction

Startable facility allows objects to be "Started" after they are created, and/or to be "Stopped" once they are released. The objects are instantiated eagerly, that means container will create the first instance without you having to explicitly call container.Resolve. This is mostly useful for singleton background services that you want to have running for the entire lifespan of your application.

Starting with version 2.5 of Windsor, the facility offers two modes of working - aggressive (default, same as in previous versions) and new - optimized for usage of single install call.

Following code samples assume that the kernel with registered facility is in scope
using Castle.Facilities.Startable;
IKernel container = new DefaultKernel();

Making components startable

There are couple of ways of making the component startable.

IStartable interface

Facility registers as startable all components implementing Castle.Core.IStartable interface
public interface IStartable
{
    void Start();
    void Stop();
}

When you implement it, you can register the component just like any other usual component (like in the example above) and it will just work.

POCO approach

Startable components do not need to implement IStartable. You can make almost any component startable, with explicit registration
container.Register(
    Component.For<PocoComponent>()
        .StartUsingMethod("Begin")
        .StopUsingMethod("End")
    );

Both StartUsingMethod and StopUsingMethod are extension methods living in facility's namespace.

You can skip either Start or Stop method if you don't need it.
Image
Requirements

Stop and Start methods have to be public, have return type of 'void' and zero parameters.

 

Strongly typed POCO

You can also use strongly typed version of the above code:
container.Register(
   Component.For<PocoComponent>()
      .StartUsingMethod(c => c.Begin)
      .StopUsingMethod(c => c.End)
   );

No dedicated initialization method

If the constructor is de-facto your initialization method of the object, use Start extension method.
container.Register(
   Component.For<PocoComponent>()
      .Start()
   );

That way your component will be eagerly instantiated just like when you would have called StartUsingMethod.



XML configuration

As most facilities, you can also configure Startable Facility via XML config file

If you don't register the facility in code, you can register it in config file:
<facility id="startable"
    type="Castle.Facilities.Startable.StartableFacility, Castle.Windsor" / >

And register your startable components using additional startable attributes:
<component id="mycomponent"
    type="Namespace.MyComponent, Assembly"
    startable="true" startMethod="StartListener" stopMethod="StopListener" / >

You need to specify startable="true" (which is equivalent to Start extension method discussed above) and optionally either startMethod, stopMethod or both.

Aggressive (old) mode

For backward compatibility this mode is the default, so you just need to add the facility to the container.

container.AddFacility<StartableFacility>();

Assuming we have a startable component, that prints out every step of its lifetime to the console like this...
public class Startable : IStartable
{
   public Startable()
   {
      Console.WriteLine("Created!");
   }

   public void Start()
   {
      Console.WriteLine("Started!");
   }

   public void Stop()
   {
      Console.WriteLine("Stopped!");
   }
}

// later in code
container.Register(Component.For<Startable>());
Console.WriteLine("Registered!");

container.Dispose();
Console.WriteLine("Released!");

If we execute this code, the following will be printed out:
Created!
Started!
Registered!
Stopped!
Released!

Image
Notice

Notice that component was instantiated and started during its registration and that we didn't resolve the component explicitly.





Deferred mode - Optimized for single call to Install

If you're using three step approach to interacting with Windsor and registering all your components during a single call to container.Install you can take another route with the facility, which offers better performance and behaves differently.

Image
Prefer deferred mode

Due to backward compatibility the deferred mode is off by default. However when possible you should prefer this mode over the old one.



When using this approach the facility is not trying aggressively to instantiate your components right on the spot, but instead waits for the end of the call to Install. Only at this point it will resolve and start all the startable components.

Image
Deferred mode will thrown when component can't be resolved

Using optimized mode, it is assumed that when the call to Install ends all components should be correctly configured and resolvable so that if Windsor can't resolve a component it will consider this an error and throw an exception, and not silently wait for the missing dependency to appear, like the old mode. When for some reasons you want to disable the exception and let the component just silently not start you can use DeferredTryStart method.



How to activate it

The optimized mode is not the default so you need to enable it explicitly when registering the facility:
container.AddFacility<StartableFacility>(f => f.DeferredStart());

If you want to disable the fail fast behavior, which throws exception when the component can not be started, you can do it by calling DeferredTryStart method.

container.AddFacility<StartableFacility>(f => f.DeferredTryStart());



External resources

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