Wednesday, December 1, 2010

Registering definitions programmatically with Spring.net

During the last couple of years I've been using Spring.net framework across different projects, and I must confess that I like it a lot, especially how it lets me write code that is clean and decoupled. Something that comes handy both for maintenance and unit testing.

But one of the things that bothers me, and many people, is having to deal with xml configuration, there are some Fluent Spring libraries spring around but none of them convinced me 100%, also it seemed to be something fun to dig into and get to learn a little more about how spring works, so I've started doing some research and found that spring already has an ObjectDefinitionBuilder which ensures the creation of valid definitions, I started to write some code to see where I could get.


After some testing I ended with these interfaces:

public interface IDefinition
 {
        IDefinition Singleton();
        IDefinition Prototype();

        IDefinition Factory(Type factoryType, string methodName);
        
        IDefinition ConstructorArgument(object value);
        IDefinition ConstructorArgument(Type referenceType);

        IDefinition Property(string propertyName, object value);
        IDefinition Property(string propertyName, Type dependencyType);
        IDefinition StaticFactory(Type factoryType, string methodName);
        IDefinition AddAlias(Type type);
        IDefinition AddAlias(string alias);
 }

as an entry point I defined the following extension method for the IApplicationContext interface

public static void Register(this IApplicationContext context, Type type, Func<IDefinition, object> definition = null)
        {
            if (definition == null)
                definition = c => c;

            using (var def = new Definition(context, type))
                definition(def);
        }

        public static void Register(this IApplicationContext context, Type type)
        {
           Register(context, type, null);
        }

and now some tests to see how that is used from the code,

[TestMethod]
public void RegisterSimpleSingleton()
{
    Context.Register(typeof(EmptyService), d => d.Singleton());
    Verify.IsSingleton<EmptyService>();
}

[TestMethod]
public void RegisterWithFactory()
{
     Context.Register(typeof(ServiceFactory));
     Context.Register(typeof(ServiceWithConstructor), d => d.Factory(typeof(ServiceFactory), "CreateService"));

     Verify.CanResolve<ServiceWithConstructor>();
}


I don't want to make this post long, if you feel curious you can dig through the code in here: google code repository

Some other things that I will explain in future posts and are already included in the google code repository is:

- Generic Type definitions: Same as code above but with generic methods
- Configuring Stereotypes: Scan all types of an assembly that fulfill an specific filter and define them. This was the real motivation of my research, an example could be, register all non-abstract types that implement the IPresenter interface, or get all types that implement an interface that has the [ServiceContract] attribute and register them with the ServiceHostFactory so they can be hosted in WCF, and the list goes on.

No comments:

Post a Comment