Spring.NET: programatically add objects to the existing (XML) application context

My experience is that Spring.NET configuration files tend to grow very large. As far as I can figure, there are two principal problems that arise from this:

  1. The configuration files get difficult to read and maintain
  2. It gets easier to introduce errors in the configuration because of its size

In general, I am in favour of keeping configuration files as small as possible. I often work with web applications that can (quite) easily be redeployed to the production environment, hence I always ask the question “will this value ever change between environments or deployments” when considering introducing a new configuration part.

Now, the Spring XML configuration usually serves two main purposes; to wire together the application, and to provide values that should be possible to change between deployments of the application or for different environments. The first purpose, I would argue does not necessarily need to be in the XML configuration. Rather, if this is done in code, we get the benefit that the compiler will tell us right away if there are typos or missing references. If this wiring is in the XML configuration file, such errors will not surface until the application starts.

So, the question that I had, was how Spring context wiring could be combined in code and in XML. I found one way of doing it, but it is only applicable to singleton objects.

Say, for instance that we have an object “something” that we wish to have configured in XML:

  <object id="something" type="SpringTest.Something, SpringTest" singleton="false"/>

Then, we have a class that we want to initialize in code:

class Foo
{
    public Foo() { }
    private Something _s;
    Something S
    {
        set { _s = value; }
        get { return _s; }
    }
}

Now, we see that Foo has a dependency on Something; it needs an instance of Something to be injected. We can use the Spring context to do this after we have created the instance of Foo:

IApplicationContext context = ContextRegistry.GetContext();
Foo f = new Foo();
context.ConfigureObject(f, "fooPrototype");

But Spring does not yet know that the Foo instance needs to be injected Something. Hence, we need to tell Spring that by creating what I would call a “prototype” or “template” object configuration:

<object id="fooPrototype" type="ContextTestProject.Foo, ContextTestProject">
   <property name="S" ref="something"></property>
</object>

The final step is then to register our newly created object in the Spring context:

XmlApplicationContext xmlContext = context as XmlApplicationContext;
xmlContext.ObjectFactory.RegisterSingleton("foo", f);

After this, the Foo instance is available for the application in the Spring context.