Castle EventWiring Configuration: Programmatically

One of the greatest things about the Castle Windsor Inversion of control container is the ability to create ‘facilities’ that take advantage of the container.  One such facility is the ‘EventWiring’ facility.

An example of configuring this via xml:

<component id="notification.service"
                  service="MyEventSample.INotificationService, MyEventSample"
                  type="MyEventSample.DefaultNotificationService, MyEventSample" >
            <subscribers>
               <subscriber id="SuccessSubscriber"
                        event="Succeeded"
                        handler="OnSuccess"/>
               <subscriber id="FailedSubscriber"
                        event="Failed"
                        handler="OnFailure"/>
            </subscribers>
         </component>

This is good, but what if I want to do the above programmatically?   Castle Windsor provides a fluent interface to help register components and set up their properties, etc… 

Here is an example:

container.AddComponent<TheService>("TheService");
            container.Register(Component.For<INotificationService>()
                .ImplementedBy<DefaultNotificationService>()
                    .Configuration(Child.ForName("subscribers")
                                         .Eq(
                                                Child.ForName("subscriber").Eq(
                                                    Attrib.ForName("id").Eq("SuccessSubscriber"),
                                                    Attrib.ForName("event").Eq("Succeeded"),
                                                    Attrib.ForName("handler").Eq("OnSuccess")
                                                ),
                                                Child.ForName("subscriber").Eq(
                                                    Attrib.ForName("id").Eq("FailedSubscriber"),
                                                    Attrib.ForName("event").Eq("Failed"),
                                                    Attrib.ForName("handler").Eq("OnFailure")
                                                )
                                         )
                                   )
                              );

(You can learn more about this from the component registration tests in the trunk)

Ayende also pointed out in a recent blog post how to combine both xml configuration with programmatically registering components.

var container = new WindsorContainer(new XmlInterpreter());
container.Register(
	AllTypes.Of(typeof (ConsumerOf<>))
		.FromAssembly(typeof(Program).Assembly)
	);

I do especially like the ability to register all components of a certain type in an assembly.  I’ve done this with my asp.net mvc controllers –> services –> dao – each in a separate assembly and easy to register all of a certain type.

MvcContrib provides the capability of registering your controllers.  Let me show a simple example of how I’ve done this.

Again, I have 3 assemblies – one for my controllers, another for my services, and then another for my Dao’s (Repositories):

So, in my global.cs – I register like this:

protected virtual void InitializeWindsor()

        {

            Logger.GeneralLogger.Info("InitializeWindsor");

            
             IWindsorContainer _container = new WindsorContainer();

            ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));

            Logger.GeneralLogger.Info("RegisterControllers");

            //Register Controllers

            _container.RegisterControllers(Assembly.Load("Bistro.Controllers"));

            //Register Services

            _container.RegisterBistroServices(true);

            //Register Daos

            _container.RegisterBistroData();

        }

Example of the services:

public static void RegisterBistroServices(this IWindsorContainer _container, bool isTransactional)

        {

            _container.Register(

                        AllTypes.Pick().FromAssemblyNamed("Bistro.Services")

                        .Configure(c => c.LifeStyle.Transient)

                        //.Configure(c => c.AddAttributeDescriptor("isTransactional", "true"))

                        .If(s => s.Name.Contains("Service"))

                        .WithService.FirstInterface());

        }

I am struggling with the Dao’s however, so I’m currently using:

(But looking on how to refactor it)

Assembly daos = Assembly.Load("Bistro.Data");

            Type[] daoTypes = daos.GetTypes();

            foreach (Type daoType in daoTypes)

            {

                if (daoType.BaseType != null)

                {

                    if (daoType.Name != "GenericDao`1" && daoType.BaseType.Name.Contains("GenericDao"))

                    {

                        try

                        {

                            Type serviceType = daoType.GetInterface(string.Concat("I", daoType.Name));

                            //_container.AddComponent(daoType.Name, serviceType, daoType);

                            _container.Register(Component.For(serviceType).ImplementedBy(daoType).LifeStyle.Transient);

                        }

                        catch (Exception ex)

                        {

                            throw new BistroException("Initialization Error " + ex.Message, ex);

                        }

                    }

                }

            }

The problem I have here is that it uses a base type as well as a service for each.

ie.

MyDao : GenericDaoWithTypedId<DomainObject, Guid>, IMyDao

MySecondDao : GenericDaoWithTypedId<DomainObject, Guid>, IMySecondDao

So, if you have a solution for this one, let me know – I’d love to clean up the Dao so it looks more like the service’s registration above  🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s