Chapter 3. Objects, Object Factories, and Application Contexts

3.1. Introduction

(Available in 1.0)

The Spring.Core assembly provides the basis for the Spring.NET Inversion of Control (IoC - sometimes also referred to as Dependency Injection) features (see Section 2.1, “Inversion of Control” for some additional material describing this software engineering principle). The IObjectFactory interface from the Spring.Core assembly provides an advanced configuration mechanism capable of managing objects of any nature, using potentially any kind of storage facility. The IApplicationContext interface from the same assembly builds on top of the functionality provided by the IObjectFactory interface, complementing it with features such as integration with Spring.NET's Aspect Oriented Programming (AOP) features and message resource handling (for use in internationalization).

In short, the IObjectFactory provides the configuration framework and basic functionality, while the IApplicationContext adds more enterprise-centric functionality to it. In general, the IApplicationContext is a complete superset of the IObjectFactory, and any description of IObjectFactory capabilities and behavior should be considered to apply to IApplicationContexts as well.

This chapter is divided into two parts, with the first part covering the basic principles that apply to both the IObjectFactory and IApplicationContext, with the second part covering those features that apply only to the IApplicationContext interface.

If you are new to Spring.NET or IoC containers in general, you may want to consider starting with Chapter 16, Quickstarts, which contains a number of introductory level examples that actually demonstrate a lot of what is described in detail below. Don't worry if you don't absorb everything at once... those examples serve only to paint a picture of how Spring.NET hangs together in really broad brushstrokes. Once you have finished with those examples, you can come back to this section which will fill in all the fine detail.

3.2. Introduction to the IObjectFactory, IApplicationContext, and IObjectDefinition

3.2.1. The IObjectFactory and IApplicationContext

The IObjectFactory is the actual container that instantiates, configures, and manages a number of objects. These objects typically collaborate with one another, and thus can be said to have dependencies between themselves. These dependencies are reflected in the configuration data used by the IObjectFactory (although some dependencies may not be visible as configuration data, but rather be a function of programmatic interactions between objects at runtime).

An IObjectFactory is represented by the Spring.Objects.Factory.IObjectFactory interface, of which there are multiple implementations. The most commonly used simple IObjectFactory is the Spring.Objects.Factory.Xml.XmlObjectFactory. Interaction with the IObjectFactory interface is discussed in Section 3.7, “Interacting with the IObjectFactory”. Additional features offered by the IApplicationContext are discussed in section Section 3.12, “Introduction to the IApplicationContext”.

As mentioned previously in the introduction, one of the central tenets of the Spring.NET framework is non-invasiveness. Quite simply, your application code should not depend on any of the Spring.NET APIs. However, if one is going to take advantage of the features provided by Spring.NET's IoC container, through the use of either the IObjectFactory or the Spring.Context.IApplicationContext interfaces, at some point one has to instantiate an appropriate implementation of either of these two core interfaces. This can happen explicitly in user code via the use of the new operator (in C# - VB.NET developers have the equivalent New operator); or more easily by using a custom configuration section in the standard .NET application (or web) configuration file. Once the container has been created you may never need to explicitly interact with it again in your code.

What follows are some examples of how one can instantiate an actual implementation of the IObjectFactory interface. In the following example an object factory, complete with object definitions describing the services that we want to wire up and expose, is created from the contents of the objects.xml file; this file is passed in as an argument to one of the constructors of the XmlObjectFactory class.

[C#]
IResource input = new FileSystemResource ("objects.xml");
IObjectFactory factory = new XmlObjectFactory(input);

The above example uses Spring.NET's IResource abstraction. The IResource interface provides a simple and uniform interface to a wide array of IO resources that can represent themselves as System.IO.Streams. The IResource abstraction is explained further in Section 3.11, “The IResource abstraction”. These resources are most frequently files or URLs but can also be resources that have been embedded inside a .NET assembly. A simple URI syntax is used to describe the location of the resource, which follows the standard conventions for files, i.e. file://object.xml and other well known protocols such as http.

As previously mentioned, one is more likely to use the IApplicationContext interface. Any of the IApplicationContext implementations can be instantiated explicitly by specifying IResource URI locations to the constructor. Multiple configuration files can used to construct an IApplicationContext as shown below.

IApplicationContext context = new XmlApplicationContext(
	"file://objects.xml",
	"assembly://MyAssembly/MyProject/objects-dal-layer.xml");

// of course, an IApplicationContext is also an IObjectFactory...
IObjectFactory factory = (IObjectFactory) context;

The following snippet shows the use of the URI syntax for referring to a resource that has been embedded inside a .NET assembly, assembly://<AssemblyName>/<NameSpace>/<ResourceName>

[Note]
To create an embedded resource using Visual Studio you must set the Build Action of the .xml configuration file to Embedded Resource in the file property editor. Also, you will need to explicitly rebuild the project containing the configuration file if it is the only change you make between successive builds. If using NAnt to build, add a <resources> section to the csc task. For example usage, look at the Spring.Core.Tests.build file included the distribution.

The preferred way to create an IApplicationContext or IObjectFactory is to use a custom configuration section in the standard .NET application configuration file (one of App.config or Web.config). A custom configuration section that creates the same IApplicationContext as the previous example is

<spring>
  <context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
    <resource uri="file://objects.xml"/>
    <resource uri="assembly://MyAssembly/MyProject/objects-dal-layer.xml"/>
  </context>
</spring>

The context type (specified as the value of the type attribute of the context element) is wholly optional, and defaults to the Spring.Context.Support.XmlApplicationContext class, so the following XML snippet is functionally equivalent to the first.

<spring>
  <context>
    <resource uri="file://objects.xml"/>
    <resource uri="assembly://MyAssembly/MyProject/objects-dal-layer.xml"/>
  </context>
</spring> 

To acquire a reference to an IApplicationContext using a custom configuration section, one simply uses the following code; please note that the string literal 'spring/context' is not arbitrary... you must use this string value (a constant is available in the AbstractApplicationContext class).

IApplicationContext ctx
        = ContextRegistry.GetContext();

The ContextRegistry is used to both instantiate the application context and to perform service locator style access to other objects. (See Section 3.17, “Service Locator access” for more information). The glue that makes this possible is an implementation of the Base Class Library (BCL) provided IConfigurationSectionHandler interface, namely the Spring.Context.Support.ContextHandler class. The handler class needs to be registered in the configSections section of the .NET configuration file as shown below.

<configSections>
  <sectionGroup name="spring">
    <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
  </sectionGroup>
</configSections> 

This declaration now enables the use of a custom context section starting at the spring root element.

In some usage scenarios, user code will not have to explicitly instantiate an appropriate implementation of the IObjectFactory interface, since Spring.NET code will do it. For example, the ASP.NET web layer provides support code to load a Spring.NET IApplicationContext automatically as part of the normal startup process of an ASP.NET web application. Similar support for WinForms applications is being investigated.

While programmatic manipulation of IObjectFactory instances will be described later, the following sections will concentrate on describing the configuration of objects managed by IObjectFactory instances.

An IObjectFactory configuration consists of, at its most basic level, definitions of one or more objects that the IObjectFactory will manage. In an XML based factory these are defined as one or more object elements inside a top-level objects element.

<objects xmlns="http://www.springframework.net" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://www.springframework.net
		http://www.springframework.net/xsd/spring-objects.xsd">
  <object id="..." type="...">
  ...
  </object>
  <object id="...." type="...">
  ...
  </object>
  ...
</objects>

Spring.NET comes with an XSD schema to make the validation of the XML object definitions a whole lot easier. The XSD document is thoroughly documented so feel free to take a peak inside (see Appendix A, Spring.NET's spring-objects.xsd). The XSD is currently used in the implementation code to validate the XML document. The XSD schema serves a dual purpose in that it also facilitates the editing of XML object definitions inside an XSD aware editor (typically VisualStudio.NET) by providing validation (and Intellisense support in the case of VisualStudio.NET). You may wish to refer to Chapter 15, Visual Studio.NET Integration for more information regarding such integration. You can also obtain the XSD that supports the latest release from the web at spring-objects.xsd.

Your XML object definitions can also be defined within the standard .NET application configuration file by registering the Spring.Context.Support.DefaultSectionHandler class as the configuration section handler for inline object definitions. This allows you to completely configure one or more IApplicationContext instances within a single standard .NET application configuration file as shown in the following example.

<configuration>

  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>

  <spring>

    <context>
      <resource uri="config://spring/objects"/>
    </context>
       
    <objects>
        ...
    </objects>

  </spring>

</configuration>

Other options available to structure the configuration files are described in Section 3.14.1, “Context Hierarchies” and Section 3.16, “Importing Object Definitions from One File Into Another”.

The IApplicationContext can be configured to register other resource handlers, custom parsers to integrate user-contributed XML schema into the object definitions section, type converters, and define type aliases. These features are discussed in section Section 3.13, “Configuration of IApplicationContext”

3.2.2. The IObjectDefinition

Object definitions describe objects managed by an IObjectFactory or IApplicationContext. Object definitions contain the following information:

  • The object type, which is the actual implementation class (the .NET System.Type) of the object being described in the object definition.

  • Object behavioral configuration elements, which state how the object should behave in the Spring.NET IoC container (i.e. prototype or singleton, autowiring mode, dependency checking mode, initialization and destruction methods).

  • Property values to set in the newly created object. An example would be the number of threads to use in an object that manages a worker thread pool (either specified as a property or as a constructor argument), or the System.Type that should be used to create the thread pool.

  • Other objects your object needs to do its work, i.e. collaborators (also specified as properties or as constructor arguments). These can also be called dependencies.

In the list above, we mentioned the use of property setters and constructor arguments. Spring.NET supports two types of IoC: Type 2 and Type 3 (Constructor Dependency Injection and Setter Dependency Injection respectively). What that basically means is that when new objects are constructed by the IoC container you can set properties of the object using both regular property setters, and also directly as arguments that you specify to a constructor.

The concepts listed above directly translate to a set of elements the object definition consists of. These elements are listed below, along with a link to further documentation about each of them.

3.2.3. Object Creation

Every object definition needs to know the type (the .NET System.Type) of the object being defined ( see Section 3.2.3.3, “Object creation via an instance factory method”, and Section 3.6, “Abstract and Child object definitions”for the exceptions). In the much more common case where the IObjectFactory itself directly creates the object instance by calling one of the objects constructors the type attribute specifies the type of the object that is to be instantiated. In the less common case where the IObjectFactory calls a so-called factory method on a type to create the object instance, the type attribute specifies the actual type containing the factory method. The type of the object returned from the invocation of this factory method may be the same type, or another type entirely, it doesn't matter.

3.2.3.1. Object creation via constructor invocation

When creating an object using the constructor approach, there are no special requirements as to what this class is or how it is implemented (i.e. your class does not have to implement a special interface to make it Spring.NET compatible), other than the fact that it must not be an interface. Just specifying the object type (and the assembly into which it has been compiled) should be enough. However, depending on what type of IoC you are going to use for that specific object, you may need to create a default constructor (i.e. a constructor that has no parameters) in the source code definition of your class.

The XmlObjectFactory implementation of the IObjectFactory interface can consume object definitions that have been defined in XML, for example...

<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"/>

This XML fragment describes an object definition that will be identified by the exampleObject name, instances of which will be of the Examples.ExampleObject type that has been compiled into the ExamplesLibrary assembly. Take special note of the structure of the type attribute's value... the namespace-qualified name of the class is specified, followed by a comma, followed by (at a bare minimum) the name of the assembly that contains the class. In the preceding example, the ExampleObject class is defined in the Examples namespace, and it has been compiled into the ExamplesLibrary assembly.

The name of the assembly that contains the type must be specified in the type attribute. Furthermore, it is recommended that you specify the fully qualified assembly name [1] in order to guarantee that the type that Spring.NET uses to instantiate your object (s) is indeed the one that you expect. Usually this is only an issue if you are using classes from (strongly named) assemblies that have been installed into the Global Assembly Cache (GAC).

If you are defining classes that have been compiled into assemblies that are available to your application (such as the bin directory in the case of ASP.NET applications) via the standard assembly probing mechanisms, then you can specify simply the name of the assembly (e.g. ExamplesLibrary.Data)... this way, when (or if) the assemblies used by your application are updated, you won't have to change the value of every <object/> definition's type attribute to reflect the new version number (if the version number has changed)... Spring.NET will automatically locate and use the newer versions of your assemblies (and their attendant classes) from that point forward.

3.2.3.2. Object creation via a static factory method

When defining an object which is to be created using a static factory method, along with the type attribute which specifies the type containing the static factory method, another attribute named factory-method is needed to specify the name of the factory method itself. Spring.NET expects to be able to call this method (with an optional list of arguments as described later) and get back a live object, which from that point on is treated as if it had been created normally via a constructor. One use for such an object definition is to call static factories in legacy code.

Following is an example of an object definition which specifies that the object is to be created by calling a factory-method. Note that the definition does not specify the type (class) of the returned object, only the type containing the factory method. In this example, CreateInstance must be a static method.

<object id="exampleObject"
      type="Examples.ExampleObjectFactory, ExamplesLibrary"
      factory-method="CreateInstance"/>

The mechanism for supplying (optional) arguments to the factory method, or setting properties of the object instance after it has been returned from the factory, will be described shortly.

3.2.3.3. Object creation via an instance factory method

Quite similar to using a static factory method to create an object, is the the use of an instance (non-static) factory method, where a factory method of an existing object from the factory is called to create the new object.

To use this mechanism, the type attribute must be left empty, and the factory-object attribute must specify the name of an object in the current or an ancestor object factory which contains the factory method. The factory method itself should still be set via the factory-method attribute.

Following is an example...

<!-- the factory object, which contains an instance method called 'CreateInstance' -->
<object id="exampleFactory" type="..."/>
<!-- the object that is to be created by the factory object -->
<object id="exampleObject"
      factory-method="CreateInstance"
      factory-object="exampleFactory"/>

Although the mechanisms for setting object properties are still to be discussed, one implication of this approach is that the factory object itself can be managed and configured via Dependency Injection, by the container.

3.2.4. Object creation of generic types

Generic types can also be created in much the same manner an non-generic types.

3.2.4.1. Object creation of generic types via constructor invocation

The following examples shows the definition of simple generic types and how they can be created in Spring's XML based configuration file.

namespace GenericsPlay
{
    public class FilterableList<T>
    {
        private List<T> list;
        
        private String name;

        public List<T> Contents
        {
            get { return list; }
            set { list = value; }
        }

        public String Name
        {
            get { return name; }
            set { name = value; }
        }
        
        public List<T> ApplyFilter(string filterExpression)
        {
            /// should really apply filter to list ;)
            return new List<T>();
        }

    }
}

The XML configuration to create and configure this object is shown below

<object id="myFilteredIntList" type="GenericsPlay.FilterableList&lt;int>, GenericsPlay">
  <property name="Name" value="My Integer List"/>
</object>

There are a few items to note in terms how to specify a generic type. First, the left bracket that specifies the generic type, i.e. <, is replaced with the string &lt; due to XML escape syntax for the less than symbol. Yes, we all realize this is less than ideal from the readability point of view. Second, the generic type arguments can not be fully assembly qualified as the comma is used to seperate generic type arguments. Alternative characters used to overcome the two quirks can be implemented in the future but so far, all proposals don't seem to help clarify the text. The suggested solution to improve readability is to use type aliases as shown below.candidate

<typeAliases>
 <alias name="GenericDictionary" type=" System.Collections.Generic.Dictionary&lt;,>" />
 <alias name="myDictionary" type="System.Collections.Generic.Dictionary&lt;int,string>" />
</typeAliases>

So that instead of something like this

<object id="myGenericObject" 
        type="GenericsPlay.ExampleGenericObject&lt;System.Collections.Generic.Dictionary&lt;int , string>>, GenericsPlay" />

It can be shortened to

<object id="myOtherGenericObject" 
        type="GenericsPlay.ExampleGenericObject&lt;GenericDictionary&lt;int , string>>, GenericsPlay" />

or even shorter

<object id="myOtherOtherGenericObject" 
        type="GenericsPlay.ExampleGenericObject&lt;MyIntStringDictionary>, GenericsPlay" />

Refer to Section 3.13, “Configuration of IApplicationContext” for additional information on using type aliases.

3.2.4.2. Object creation of generic types via static factory method

The following classes are used to demonstrate the ability to create instances of generic types that themselves are created via a static generic factory method.

public class TestGenericObject<T, U>
{
    public TestGenericObject()
    {
    }

    private IList<T> someGenericList = new List<T>();
    
    private IDictionary<string, U> someStringKeyedDictionary =
        new Dictionary<string, U>();

    public IList<T> SomeGenericList
    {
        get { return someGenericList; }
        set { someGenericList = value; }
    }

    public IDictionary<string, U> SomeStringKeyedDictionary
    {
        get { return someStringKeyedDictionary; }
        set { someStringKeyedDictionary = value; }
    }

}

The accompanying factory class is

public class TestGenericObjectFactory
{
    public static TestGenericObject<V, W> StaticCreateInstance<V, W>()
    {
        return new TestGenericObject<V, W>();
    }

    public TestGenericObject<V, W> CreateInstance<V, W>()
    {
        return new TestGenericObject<V, W>();
    }
}

The XML snippit to create an instance of TestGenericObject where V is a List of integers and W is an integer is shown below

<object id="myTestGenericObject"
        type="GenericsPlay.TestGenericObjectFactory, GenericsPlay"
        factory-method="StaticCreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"
/>

The StaticCreateInstance method is responsible for instantiating the object that will be associated with the id 'myTestGenericObject'.

3.2.4.3. Object creation of generic types via instance factory method

Using the class from the previous example the XML snippit to create an instance of a generic type via an instance factory method is shown below

<object id="exampleFactory" type="GenericsPlay.TestGenericObject&lt;int,string>, GenericsPlay"/>

<object id="anotherTestGenericObject"
        factory-object="exampleFactory" 
        factory-method="CreateInstance&lt;System.Collections.Generic.List&lt;int>,int>"/>

This creates an instance of TestGenericObject<List<int>,int>

3.2.5. The object identifiers (id and name)

Every object has one or more ids (also called identifiers, or names; these terms refer to the same thing). These ids must be unique within the IObjectFactory or IApplicationContext that the object definition is hosted in. An object definition will almost always have only one id, but if an object has more than one id, the extra ones can essentially be considered aliases.

In an XML object definition, the id or name attributes of the object element are used to specify the object definition's id (s), and at least one id must be specified in one or both of these attributes. The id attribute allows you to specify one id, and since it is marked in the Spring.NET XSD as a bona-fide XML element ID attribute, the parser is able to do some extra validation when other elements point back to this one. As such, it is the preferred way to specify an object id. However, the XML specification does limit the characters that are legal in XML IDs. This is usually not a constraint, but if you have a need to use one of these characters, or want to introduce aliases to the object, you may also or instead specify one or more object ids (separated by a comma (,) or semicolon (;)) via the name attribute.

3.2.6. Singleton & Prototype Scope

Objects can be deployed in one of two modes: singleton or non-singleton (the latter is also called a prototype, although the term is used loosely as it doesn't quite fit). When an object definition is set to the singleton mode, only one shared instance of the object will be managed, and all requests for objects with an id or ids matching that object definition will result in that one specific object instance being returned (i.e. the object defined by the object definition will only ever be created once).

The non-singleton, prototype mode of an object deployment results in the creation of a new object instance every time a request for that specific object is received. For example, this is ideal for those situations where each user needs an independent user object or something similar.

Object definitions operate in singleton mode by default, unless you specify otherwise. Keep in mind that by changing the mode to non-singleton (prototype), each request for an object will result in a new instance and this might not be what you actually want. So only change the mode to prototype when absolutely necessary.

[Note]
When deploying an object in the prototype mode, the lifecycle of the object changes slightly. By definition, Spring.NET cannot manage the complete lifecycle of a non-singleton / prototype object, since after it is created, it is given to the client and the container does not keep track of it at all any longer. You can think of Spring.NET's role when talking about a non-singleton / prototype object as a replacement for the 'new' operator. Any lifecycle aspects past that point have to be handled by the client. The lifecycle of an object in the IObjectFactory is further described in Section 3.5.1, “Lifecycle interfaces”

In the XML fragment below, two objects are declared of which one is defined as a singleton, and the other one as a prototype. The exampleObject object is created each and every time a client asks the IObjectFactory for this object, whereas the yetAnotherExample object is only created once; a reference to the exact same instance is returned on each request for this object.

<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary"
  singleton="false"/>
<object name="yetAnotherExample" type="Examples.ExampleObjectTwo, ExamplesLibrary"
  singleton="true"/>

The lazy-init attribute gives you control over when the singleton is instantiated. A common variation on the singleton design pattern is to lazily create the object, that is to create it only when it is first used. By default, the lazy-init attribute is set to false instructing the IoC container to pre-instantiate singletons object when the container is initialized. Setting the attribute to false will delay the creation until the object is first requested from the container, either directly from a user request or as a result of the resolving object dependencies.

3.3. Properties, collaborators, autowiring and dependency checking

3.3.1. Setting object properties and collaborators

Inversion of Control has already been referred to as Dependency Injection. The basic principle is that objects define their dependencies (i.e. the other objects they work with) only through constructor arguments, arguments to a factory method, or properties which are set on the object instance after it has been constructed or returned from a factory method. Then, it is the job of the container to actually inject those dependencies when it creates the object. This is fundamentally the inverse (hence the name Inversion of Control) of the object instantiating or locating its dependencies on its own using direct construction of classes (via the new operator), or something like the Service Locator pattern. While we will not elaborate too much on the advantages of Dependency Injection, it becomes evident upon usage that code gets much cleaner and reaching a higher grade of decoupling is much easier when objects do not look up their dependencies, but are provided them, and additionally do not even know where the dependencies are located and of what actual type they are.

As touched on in the previous paragraph, Inversion of Control / Dependency Injection exists in two major variants:

  • setter-based dependency injection is realized by calling property setters on your objects after invoking a no-argument constructor to instantiate your object. Spring.NET generally advocates the usage of setter-based dependency injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional.

  • constructor-based dependency injection is realized by invoking a constructor with a number of arguments, each representing a collaborator or property. Although Spring.NET generally advocates the usage of setter-based dependency injection as much as possible, it does fully support the constructor-based approach as well, since you may wish to use it with pre-existing objects which provide only multi-argument constructors, and no setters. Additionally, for simpler objects, some people prefer the constructor approach as a means of ensuring objects can not be constructed in an invalid state.

The IObjectFactory supports both of these variants for injecting dependencies into objects it manages. The configuration for the dependencies comes in the form of the IObjectDefinition class, which is used together with TypeConverters to know how to convert properties from one format to another. However, most users of Spring.NET will not be dealing with these classes directly (i.e. programmatically), but rather with an XML definition file which will be converted internally into instances of these classes, and used to load an entire IObjectFactory or IApplicationContext.

Object dependency resolution generally happens as follows:

  1. The IObjectFactory is created and initialized with a configuration which describes all the objects. Most Spring.NET users use an IObjectFactory or IApplicationContext variant that supports XML format configuration files.

  2. Each object has dependencies expressed in the form of properties or constructor arguments. These will be provided to the object, when the object is actually created.

  3. Each property or constructor-arg is either an actual definition of the value to set, or a reference to another object in the IObjectFactory. In the case of the IApplicationContext, the reference can be to an object in a parent IApplicationContext.

  4. Each property or constructor argument which is a value must be able to be converted from whatever format it was specified in, to the actual System.Type of that property or constructor argument. By default Spring.NET can convert a value supplied in string format to all built-in types, such as int, long, string, bool, etc. Additionally, when talking about the XML based IObjectFactory variants (including the IApplicationContext variants), these have built-in support for defining IList, IDictionary, and Set collection types. Spring.NET uses TypeConverter definitions to be able to convert string values to other, arbitrary types. Refer to Section 4.3, “Type conversion” for more information regarding type conversion, and how you can design your classes to be convertible by Spring.NET.

  5. It is important to realize that Spring.NET validates the configuration of each object in the IObjectFactory when the IObjectFactory is created, including the validation that properties that are object references are actually referring to valid objects (i.e. the objects being referred to are also defined in the IObjectFactory, or in a parent context in the case of IApplicationContext). However, the object properties themselves are not set until the object is actually created. For objects that have been defined as singletons and set to be pre-instantiated (such as singleton objects in an IApplicationContext), creation happens at the time that the IObjectFactory is created, but otherwise this is only when the object is requested. When an object actually has to be created, this will potentially cause a graph of other objects to be created, as its dependencies and its dependencies' dependencies (and so on) are created and assigned.

  6. You can generally trust Spring.NET to do the right thing. It will pick up configuration issues, including references to non-existent object definitions and circular dependencies, at IObjectFactory load-time. It will actually set properties and resolve dependencies (i.e. create any dependent objects if needed) as late as possible, which is when the object is actually created. This does mean that an IObjectFactory which has loaded correctly can later generate an exception when you request an object, if there is a problem creating that object or one of its dependencies. This could happen if the object throws an exception as a result of a missing or invalid property, for example. This potentially delayed visibility of some configuration issues is why IApplicationContext by default pre-instantiates singleton objects. At the cost of some upfront time and memory to create these objects before they are actually needed, you find out about configuration issues when the IApplicationContext is created, not later. If you wish, you can still override this default behavior and set any of these singleton objects to lazy-load (not be preinstantiated).

Some examples (using XML based object definitions)...

First, an example of using the IObjectFactory for setter-based dependency injection. Below is a small part of an XML file specifying some object definitions. Following is the code for the actual main object itself, showing the appropriate setters declared.

<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary">
    <property name="objectOne" ref="anotherExampleObject"/>
    <property name="objectTwo" ref="yetAnotherObject"/>
    <property name="IntegerProperty" value="1"/>
</object>

<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[C#]
public class ExampleObject
{
  private AnotherObject objectOne;
  private YetAnotherObject objectTwo;
  private int i;
  
  public AnotherObject ObjectOne
  {
    set { this.objectOne = value; }
  }
  
  public YetAnotherObject ObjectTwo
  {
    set { this.objectTwo = value; }
  }
  
  public int IntegerProperty
  {
    set { this.i = value; }
  }  
}

Now, an example of using the IObjectFactory for IoC Type 3 (Constructor Dependency Injection). Below is a snippet from an XML configuration that specifies constructor arguments and the actual object code, showing the constructor:

<object id="exampleObject" type="Examples.ExampleObject, ExamplesLibrary">
    <constructor-arg name="objectOne" ref="anotherExampleObject"/>
    <constructor-arg name="objectTwo" ref="yetAnotherObject"/>
    <constructor-arg name="IntegerProperty" value="1"/>
</object>

<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[Visual Basic.NET]
Public Class ExampleObject

    Private myObjectOne As AnotherObject
    Private myObjectTwo As YetAnotherObject
    Private i As Integer
    
    Public Sub New (
        anotherObject as AnotherObject,
        yetAnotherObject as YetAnotherObject,
        i as Integer)
        
        myObjectOne = anotherObject
        myObjectTwo = yetAnotherObject
        Me.i = i
    End Sub
End Class

As you can see, the constructor arguments specified in the object definition will be used to pass in as arguments to the constructor of the ExampleObject.

Note that Type 2 Setter Injection and Type 3 Constructor Injection IoC are not mutually exclusive... it is perfectly reasonable to use both for a single object definition, as can be seen in the following example:

<object id="exampleObject" type="Examples.MixedIocObject, ExamplesLibrary">
    <constructor-arg name="objectOne" ref="anotherExampleObject"/>
    <property name="objectTwo" ref="yetAnotherObject"/>
    <property name="IntegerProperty" value="1"/>
</object>

<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[C#]
public class MixedIocObject
{
  private AnotherObject objectOne;
  private YetAnotherObject objectTwo;
  private int i;
  
  public MixedIocObject (AnotherObject obj)
  {
    this.objectOne = obj;
  }
  
  public YetAnotherObject ObjectTwo
  {
    set { this.objectTwo = value; }
  }
  
  public int IntegerProperty
  {
    set { this.i = value; }
  }  
}

Now consider a variant of this where instead of using a constructor, Spring is told to call a static factory method to return an instance of the object

<object id="exampleObject" type="Examples.ExampleFactoryMethodObject, ExamplesLibrary"
     factory-method="CreateInstance">
    <constructor-arg name="objectOne" ref="anotherExampleObject"/>
    <constructor-arg name="objectTwo" ref="yetAnotherObject"/>
    <constructor-arg name="intProp" value="1"/>
</object>

<object id="anotherExampleObject" type="Examples.AnotherObject, ExamplesLibrary"/>
<object id="yetAnotherObject" type="Examples.YetAnotherObject, ExamplesLibrary"/>

[C#]
public class ExampleFactoryMethodObject
{
  private AnotherObject objectOne;
  private YetAnotherObject objectTwo;
  private int i;
  
  // a private constructor
  private ExampleFactoryMethodObject()
  {
  }

  public static ExampleFactoryMethodObject CreateInstance(AnotherObject objectOne,
                               YetAnotherObject objectTwo,
                               int intProp)
  {
    ExampleFactoryMethodObject fmo = new ExampleFactoryMethodObject();
    fmo.AnotherObject = objectOne;
    fmo.YetAnotherObject = objectTwo;
    fmo.IntegerProperty = intProp;
    return fmo;
  }

  // Property definitions

}

Note that arguments to the static factory method are supplied via constructor-arg elements, exactly the same as if a constructor had actually been used. These arguments are optional. Also, it is important to realize that the type of the class being returned by the factory method does not have to be of the same type as the class which contains the static factory method, although in this example it is. An instance (non-static) factory method, mentioned previously, would be used in an essentially identical fashion (aside from the use of the factory-object attribute instead of the type attribute), so will not be detailed here.

3.3.2. Constructor Argument Resolution

Constructor argument resolution matching occurs using the argument's type. When another object is referenced, the type is known, and matching can occur. When a simple type is used, such as <value>1</value>, Spring.NET cannot determine the type of the value, and so cannot match by type without help. Consider the following class, which is used for the following two sections:

using System;

namespace SimpleApp
{
  public class ExampleObject
  {
    private int years;              //No. of years to the calculate the Ultimate Answer

    private string ultimateAnswer;  //The Answer to Life, the Universe, and Everything

    public ExampleObject(int years, string ultimateAnswer)
    {
       this.years = years;
       this.ultimateAnswer = ultimateAnswer;
    }

    public string UltimateAnswer
    {
      get { return this.ultimateAnswer; }
    }

    public int Years
    {
      get { return this.years; }
    }
  }
}

3.3.2.1. Constructor Argument Type Matching

The above scenario can use type matching with simple types by explicitly specifying the type of the constructor argument using the type attribute. For example:

<object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
  <constructor-arg type="int" value="7500000"/>
  <constructor-arg type="string" value="42"/>
</object>

The type attribute specifies the System.Type of the constructor argument, such as System.Int32. Alias' are available to for common simple types (and their array equivalents). These alias' are...

Table 3.2. Type aliases

TypeAlias'Array Alias'
System.Charchar, Charchar[], Char()
System.Int16short, Shortshort[], Short()
System.Int32int, Integerint[], Integer()
System.Int64long, Longlong[], Long()
System.UInt16ushortushort[]
System.UInt32uintuint[]
System.UInt64ulongulong[]
System.Floatfloat, Singlefloat[], Single()
System.Doubledouble, Doubledouble[], Double()
System.Datedate, Datedate[], Date()
System.Decimaldecimal, Decimaldecimal[], Decimal()
System.Boolbool, Booleanbool[], Boolean()
System.Stringstring, Stringstring[], String()

3.3.2.2. Constructor Argument Index

Constructor arguments can have their index specified explicitly by use of the index attribute. For example:

<object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
  <constructor-arg index="0" value="7500000"/>
  <constructor-arg index="1" value="42"/>
</object>

As well as solving the ambiguity problem of multiple simple values, specifying an index also solves the problem of ambiguity where a constructor may have two arguments of the same type. Note that the index is 0 based.

3.3.2.3. Constructor Arguments by Name

Constructor arguments can also be specified by name by using the name attribute of the <constructor-arg> element.

<object name="exampleObject" type="SimpleApp.ExampleObject, SimpleApp">
  <constructor-arg name="years" value="7500000"/>
  <constructor-arg name="ultimateAnswer" value="42"/>
</object>

3.3.3. Object properties and constructor arguments in detail

As mentioned in the previous section, object properties and constructor arguments can be defined as either references to other managed objects (collaborators). The XmlObjectFactory (located in the Spring.Objects.Factory.Xml namespace) supports a number of sub-element types within its property and constructor-arg elements for this purpose.

The value element specifies a property or constructor argument as a human-readable string representation. As mentioned in detail previously, TypeConverter instances are used to convert these string values from a System.String to the actual property or argument type. Custom TypeConverter implementations in the Spring.Objects.TypeConverters namespace are used to augment the functionality offered by the .NET BCL's default TypeConverter implementations.

In the following example, we use a SqlConnection from the System.Data.SqlClient namespace of the BCL. This class (like many other existing classes) can easily be used in a Spring.NET object factory, as it offers a convenient public property for configuration of its ConnectionString property.

<objects>
  <object id="myConnection" type="System.Data.SqlClient.SqlConnection">
      <!-- results in a call to the setter of the ConnectionString property -->
      <property
          name="ConnectionString"
          value="Integrated Security=SSPI;database=northwind;server=mySQLServer"/>
  </object>
</objects>

3.3.3.1. Setting null values

The <null> element is used to handle null values. Spring.NET treats empty arguments for properties and constructor arguments as empty string instances. The following configuration demonstrates this behaviour...

<object type="Examples.ExampleObject, ExamplesLibrary">
    <property name="email"><value></value></property>
    <!-- equivalent, using value attribute as opposed to nested <value/> element...
    <property name="email" value=""/>
</object>

This results in the email property being set to the empty string value (""), in much the same way as can be seen in the following snippet of C# code...

exampleObject.Email = "";

The special <null/> element may be used to indicate a null value; to wit...

<object type="Examples.ExampleObject, ExamplesLibrary">
    <property name="email"><null/></property>
</object>

This results in the email property being set to null, again in much the same way as can be seen in the following snippet of C# code...

exampleObject.Email = null;

3.3.3.2. Setting collection values

The list, set, name-values and dictionary elements allow properties and arguments of the type IList, ISet, NameValueCollection and IDictionary, respectively, to be defined and set.

<objects>
  <object id="moreComplexObject" type="Example.ComplexObject">
      <!--
      results in a call to the setter of the SomeList (System.Collections.IList) property
      -->
      <property name="SomeList">
          <list>
              <value>a list element followed by a reference</value>
              <ref object="myConnection"/>
          </list>
      </property>
      <!--
      results in a call to the setter of the SomeDictionary (System.Collections.IDictionary) property
      -->
      <property name="SomeDictionary">
          <dictionary>
              <entry key="a string => string entry" value="just some string"/>
              <entry key-ref="myKeyObject" value-ref="myConnection"/>
          </dictionary>
      </property>
      <!--
      results in a call to the setter of the SomeNameValue (System.Collections.NameValueCollection) property
      -->
      <property name="SomeNameValue">
          <name-values>
              <add key="HarryPotter" value="The magic property"/>
              <add key="JerrySeinfeld" value="The funny (to Americans) property"/>
          </name-values>
      </property>
      <!-- 
      results in a call to the setter of the SomeSet (Spring.Collections.ISet) property 
      -->
      <property name="someSet">
          <set>
              <value>just some string</value>
              <ref object="myConnection"/>
          </set>
      </property>
  </object>
</objects>

Many classes in the BCL expose only read-only properties for collection classes. When Spring.NET encounters a read-only collection, it will configure the collection by using the getter property to obtain a reference to the collection class and then proceed to add the additional elements to the existing collection. This results in an additive behavior for collection properties that are exposed in this manner.

Note that the value of a Dictionary entry, or a set value, can also again be any of the elements:

(object | ref | idref | list | set | dictionary | name-values | value | null)

The shortcut forms for value and references are useful to reduce XML verbosity when setting collection properties. See Section 3.3.3.8, “Value and ref shortcut forms” for more information.

Please be advised that the setting of multiple values for a NameValueCollection is planned for a future release.

3.3.3.3. Setting generic collection values

Spring supports setting values for classes that expose properties based on the generic collection interfaces IList<T> and IDictionary<TKey, TValue>. The type parameter for these collections is specified by using the XML attribute element-type for IList<T> and the XML attributes key-type and value-type for IDictionary<TKey, TValue>. The values of the collection are automaticaly converted from a string to the appropriate type. If you are using your own user-defined type as a generic type parameter you will likely need to register a custom type converter. Refer to Section 3.4, “Type conversion” for more information. The implementations of IList<T> and IDictionary<TKey, TValue> that is created are System.Collections.Generic.List and System.Collections.Generic.Dictionary.

The following class represents a lottery ticket and demonstrates how to set the values of a generic IList.

public class LotteryTicket
{
    List<int> list;
    DateTime date;
    public List<int> Numbers
    {
        set { list = value; }
        get { return list; }
    }

    public DateTime Date
    {
        get { return date; }
        set { date = value; }
    }
}

The XML fragment that can be used to configure this class is shown below

<object id="MyLotteryTicket" type="GenericsPlay.Lottery.LotteryTicket, GenericsPlay">
  <property name="Numbers">
    <list element-type="int">
      <value>11</value>
      <value>21</value>
      <value>23</value>
      <value>34</value>
      <value>36</value>
      <value>38</value>
    </list>
  </property>
  <property name="Date" value="4/16/2006"/>
</object>

The following shows the definition of a more complex class that demonstrates the use of generics using the Spring.Expressions.IExpression interface as the generic type parameter for the IList element-type and the value-type for IDictionary. Spring.Expressions.IExpression has an associated type converter, Spring.Objects.TypeConverters.ExpressionConverter that is already pre-registered with Spring.

public class GenericExpressionHolder
{
    private System.Collections.Generic.IList<IExpression> expressionsList;
    private System.Collections.Generic.IDictionary<string, IExpression> expressionsDictionary;

    public System.Collections.Generic.IList<IExpression> ExpressionsList
    {
        set { this.expressionsList = value; }
    }

    public System.Collections.Generic.IDictionary<string,IExpression> ExpressionsDictionary
    {
        set { this.expressionsDictionary = value; }
    }

    public IExpression this[int index]
    {
        get { return this.expressionsList[index]; }
    }

    public IExpression this[string key]
    {
        get { return this.expressionsDictionary[key]; }
    }
}

An example XML configuration of this class is shown below

<object id="genericExpressionHolder" type="Spring.Objects.Factory.Xml.GenericExpressionHolder, Spring.Core.Tests">
  <property name="ExpressionsList">
    <list element-type="Spring.Expressions.IExpression, Spring.Core">
      <value>1 + 1</value>
      <value>date('1856-7-9').Month</value>
      <value>'Nikola Tesla'.ToUpper()</value>
      <value>DateTime.Today > date('1856-7-9')</value>
    </list>
  </property>
  <property name="ExpressionsDictionary">
    <dictionary key-type="string" value-type="Spring.Expressions.IExpression, Spring.Core">
      <entry key="zero">
        <value>1 + 1</value>
      </entry>
      <entry key="one">
        <value>date('1856-7-9').Month</value>
      </entry>
      <entry key="two">
        <value>'Nikola Tesla'.ToUpper()</value>
      </entry>
      <entry key="three">
        <value>DateTime.Today > date('1856-7-9')</value>
      </entry>
    </dictionary>
  </property>
</object>

3.3.3.4. Setting indexer properties

An indexer lets you set and get values from a collection using a familiar bracket [] notation. In the compiled class a property named Item[type] is created, where the type represent the indexer parameter type, typically a string or an int. If you use Reflector you can see this for yourself. Given this naming convention, Spring lets you configure indexer properties using the following syntax

<object id="objectWithIndexer" type="Spring.Objects.TestObject, Spring.Core.Tests"> 
  <property name="Item[0]" value="my string value"/> 
</object>

would correspond to setting an indexer in a class with the followign declaration

public class TestObject
{
  public string this[int index]
  {
    ...
  }

  ...
}

You can also change the name used to identify the indexer by adorning your indexer method declaration with the attribute [IndexerName("MyItemName")]. You would then use the string MyItemName[0] to configure the first element of that indexer.

There are some limitations to be aware in the current indexer configuration. The indexer can only be of a single parameter that is convertable from a string to the indexer parameter type. Also, multiple indexers are not supported. You can get around that last limitation currently if you use the IndexerName attribute, but future versions will accomodate this case so you don't have to make any changes to your class (if even possible!). The Spring container is intended to be as non-invasive as possible.

3.3.3.5. Inline objects

An object element inside the property element is used to define an object value inline, instead of referring to an object defined elsewhere in the container. The inline object definition does not need to have any id or name defined (indeed, if any are defined, they will be ignored).

<object id="outer" type="...">
    <!-- Instead of using a reference to target, just use an inner object -->
    <property name="target">
        <object type="ExampleApp.Person, ExampleApp">
            <property name="name" value="Tony"/>
            <property name="age" value="51"/>
        </object>
   </property>
</object>

3.3.3.6. The idref element

An idref element is simply a shorthand and error-proof way to set a property to the String id or name of another object in the container.

<object id="theTargetObject" type="...">
</object>
<object id="theClientObject" type="...">
    <property name="targetName">
        <idref object="theTargetObject"/>
    </property>
</object>

This is exactly equivalent at runtime to the following fragment:

<object id="theTargetObject" type="...">
</object>
<object id="theClientObject" type="...">
    <property name="targetName" value="theTargetObject"/>
</object>

The main reason the first form is preferable to the second is that using the idref tag will allow Spring.NET to validate at deployment time that the other object actually exists. In the second variation, the class that is having its targetName property injected is forced to do its own validation, and that will only happen when that class is actually instantiated by the container, possibly long after the container is actually up and running.

Additionally, if the object being referred to is in the same actual XML file, and the object name is the object id, the local attribute may be used, which will allow the XML parser itself to validate the object name even earlier, at parse time.

<property name="targetName">
    <idref local="theTargetObject"/>
</property>

3.3.3.7. Referring to collaborating objects

The ref element is the final element allowed inside a property definition element. It is used to set the value of the specified property to be a reference to another object managed by the container, a collaborator, so to speak. As you saw in the previous example to set collection properties, we used the SqlConnection instance from the initial example as a collaborator and specified it using a <ref object/> element. As mentioned in a previous section, the referred-to object is considered to be a dependency of the object who's property is being set, and will be initialized on demand as needed (if it is a singleton object it may have already been initialized by the container) before the property is set. All references are ultimately just a reference to another object, but there are 3 variations on how the id/name of the other object may be specified, which determines how scoping and validation is handled.

Specifying the target object by using the object attribute of the ref tag is the most general form, and will allow creating a reference to any object in the same IObjectFactory / IApplicationContext (whether or not in the same XML file), or parent IObjectFactory / IApplicationContext. The value of the object attribute may be the same as either the id attribute of the target object, or one of the values in the name attribute of the target object.

<ref object="someObject"/>

Specifying the target object by using the local attribute leverages the ability of the XML parser to validate XML id references within the same file. The value of the local attribute must be the same as the id attribute of the target object. The XML parser will issue an error if no matching element is found in the same file. As such, using the local variant is the best choice (in order to know about errors are early as possible) if the target object is in the same XML file.

<ref local="someObject"/>

Specifying the target object by using the parent attribute allows a reference to be created to an object that is in a parent IObjectFactory (orIApplicationContext) of the current IObjectFactory (or IApplicationContext). The value of the parent attribute may be the same as either the id attribute of the target object, or one of the values in the name attribute of the target object, and the target object must be in a parent IObjectFactory or IApplicationContext of the current one. The main use of this object reference variant is when there is a need to wrap an existing object in a parent context with some sort of proxy (which may have the same name as the parent), and needs the original object so it may wrap it.

<ref parent="someObject"/>

3.3.3.8. Value and ref shortcut forms

There are also some shortcut forms that are less verbose than using the full value and ref elements. The property, constructor-arg, and entry elements all support a value attribute which may be used instead of embedding a full value element. Therefore, the following:

<property name="myProperty">
    <value>hello</value>
</property>

<constructor-arg>
    <value>hello</value>
</constructor-arg>

<entry key="myKey">
    <value>hello</value>
</entry>

are equivalent to:

<property name="myProperty" value="hello"/>

<constructor-arg value="hello"/>

<entry key="myKey" value="hello"/>

In general, when typing definitions by hand, you will probably prefer to use the less verbose shortcut form.

The property and constructor-arg elements support a similar shortcut ref attribute which may be used instead of a full nested ref element. Therefore, the following...

<property name="myProperty">
    <ref object="anotherObject"/>
</property>

<constructor-arg index="0">
    <ref object="anotherObject"/>
</constructor-arg>

is equivalent to...

<property name="myProperty" ref="anotherObject"/>

<constructor-arg index="0" ref="anotherObject"/>

[Note]
The shortcut form is equivalent to a <ref object="xxx"> element; there is no shortcut for either the <ref local="xxx"> or <ref parent="xxx"> elements. For a local or parent ref, you must still use the long form.

Finally, the entry element allows a shortcut form the specify the key and/or value of a dictionary, in the form of key/key-ref and value/value-ref attributes. Therefore, the following

<entry>
  <key><ref object="MyKeyObject"/></key>
  <ref object="MyValueObject"/>
</entry>

Is equivalent to:

<entry key-ref="MyKeyObject" value-ref="MyValueObject"/>

As mentioned previously, the equivalence is to <ref object="xxx"> and not the local or parent forms of object references.

3.3.3.9. Compound property names

Note that compound or nested property names are perfectly legal when setting object properties, as long as all components of the path except the final property name are non-null. For example, in this object definition:

<object id="foo" type="Spring.Foo, Spring.Foo">
    <property name="bar.baz.name" value="Bingo"/>
</object>

3.3.4. Method Injection

For most users, the majority of the objects in the container will be singletons. When a singleton object needs to collaborate with (use) another singleton object, or a non-singleton object needs to collaborate with another non-singleton object, the typical and common approach of handling this dependency (by defining one object to be a property of the other) is quite adequate. There is however a problem when the object lifecycles are different. Consider a singleton object A which needs to use a non-singleton (prototype) object B, perhaps on each method invocation on A. The container will only create the singleton object A once, and thus only get the opportunity to set its properties once. There is no opportunity for the container to provide object A with a new instance of object B every time one is needed.

One solution to this problem is to forego some inversion of control. Object A can be aware of the container by implementing the IObjectFactoryAware interface, and use programmatic means to ask the container via a GetObject("B") call for (a new) object B every time it needs it. This is generally not a desirable solution since the object code is then aware of and coupled to Spring.NET.

Method Injection, an advanced feature of supporting IObjectFactoryAware implementations, allows this use case to be handled in a clean fashion, along with some other scenarios.

3.3.4.1. Lookup Method Injection

Lookup method injection refers to the ability of the container to override abstract or concrete methods on managed objects in the container, and to return the result of looking up another named object in the container. The lookup will typically be of a non-singleton object as per the scenario described above (although it can also be a singleton). Spring.NET implements this through a dynamically generated subclass overriding the method using the classes in the System.Reflection.Emit namespace.

In the client class containing the method to be injected, the method definition must observe the following form:

protected abstract SingleShotHelper CreateSingleShotHelper();

If the method is not abstract, Spring.NET will simply override the existing implementation. In the XmlObjectFactory case, you instruct Spring.NET to inject / override this method to return a particular object from the container, by using the lookup-method element inside the object definition. For example:

<!-- a stateful object deployed as a prototype (non-singleton) -->
<object id="singleShotHelper" class="..." singleton="false"/>

<!-- myobject uses singleShotHelper -->
<object id="myObject" type="...">
  <lookup-method name="CreateSingleShotHelper" object="singleShotHelper"/>
  <property>
    ...
  </property>
</object>

The object identified as myObject will call its own method CreateSingleShotHelper whenever it needs a new instance of the singleShotHelper object. It is important to note that the person deploying the objects must be careful to deploy the singleShotHelper object as a non-singleton (if that is actually what is needed). If it is deployed as a singleton (either explicitly, or relying on the default true setting for this flag), the same instance of singleShotHelper will be returned each time!

Note that lookup method injection can be combined with Constructor Injection (supplying optional constructor arguments to the object being constructed), and also with Setter Injection (settings properties on the object being constructed).

3.3.4.2. Arbitrary method replacement

A less commonly useful form of method injection than Lookup Method Injection is the ability to replace arbitrary methods in a managed object with another method implementation. Users may safely skip the rest of this section (which describes this somewhat advanced feature), until this functionality is actually needed.

In an XmlObjectFactory, the replaced-method element may be used to replace an existing method implementation with another. Consider the following class, with a method ComputeValue, which we want to override:

public class MyValueCalculator {

  public virtual string ComputeValue(string input) {
    // ... some real code
  }

  // ... some other methods
}

A class implementing the Spring.Objects.Factory.Support.IMethodReplacer interface is needed to provide the new (injected) method definition.

/// <summary>
/// Meant to be used to override the existing ComputeValue(string)
/// implementation in MyValueCalculator.
/// </summary>
public class ReplacementComputeValue : IMethodReplacer 
{
	public object Implement(object target, MethodInfo method, object[] arguments)
	{
		// get the input value, work with it, and return a computed result...
		string value = (string) arguments[0];
		// compute...
		return result;
	}
}

The attendant IObjectFactory definition to deploy the original class and specify the method override would look like:

<object id="myValueCalculator" type="Examples.MyValueCalculator, ExampleAssembly">
  <!-- arbitrary method replacement -->
  <replaced-method name="ComputeValue" replacer="replacementComputeValue">
    <arg-type match="String"/>
  </replaced-method>
</object>

<object id="replacementComputeValue" type="Examples.ReplaceMentComputeValue, ExampleAssembly"/>

One or more contained arg-type elements within the replaced-method element may be used to indicate the method signature of the method being overridden. Note that the signature for the arguments is actually only needed in the case that the method is actually overloaded and there are multiple variants within the class. For convenience, the type string for an argument may be a substring of the fully qualified type name. For example, all the following would match System.String.

    System.String
    String
    Str

Since the number of arguments is often enough to distinguish between each possible choice, this shortcut can save a lot of typing, by just using the shortest string which will match an argument.

3.3.5. Setting a reference using the members of other objects and classes.

This section details those configuration scenarios that involve the setting of properties and constructor arguments using the members of other objects and classes. This kind of scenario is quite common, especially when dealing with legacy classes that you cannot (or won't) change to accommodate some of Spring.NET's conventions... consider the case of a class that has a contructor argument that can only be calculated by going to say, a database. The MethodInvokingFactoryObject handles exactly this scenario ... it will allow you to inject the result of an arbitrary method invocation into a constructor (as an argument) or as the value of a property setter. Similary, PropertyRetrievingFactoryObject and FieldRetrievingFactoryObject allow you to retrieve values from another objects property or field value. These classes implement the IFactoryObject interface which indicates to Spring.NET that this object is itself a factory and the factories product, not the factory itself, is what will be associated with the object id. Factory objects are discussed futher in Section 3.5.3, “IFactoryObject”

3.3.5.1. Setting a reference to the value of property.

The PropertyRetrievingFactoryObject is an IFactoryObject that addresses the scenario of setting one of the properties and / or constructor arguments of an object to the value of a property exposed on another object or class. One can use it to get the value of any public property exposed on either an instance or a class (in the case of a property exposed on a class, the property must obviously be static).

In the case of a property exposed on an instance, the target object that a PropertyRetrievingFactoryObject will evaluate can be either an object instance specified directly inline or a reference to another arbitrary object. In the case of a static property exposed on a class, the target object will be the class (the .NET System.Type) exposing the property.

The result of evaluating the property lookup may then be used in another object definition as a property value or constructor argument. Note that nested properties are supported for both instance and class property lookups. The IFactoryObject is discussed more generally in Section 3.5.3, “IFactoryObject”.

Here's an example where a property path is used against another object instance. In this case, an inner object definition is used and the property path is nested, i.e. spouse.age.

<object name="person" type="Spring.Objects.TestObject, Spring.Core.Tests">
  <property name="age" value="20"/>
  <property name="spouse">
    <object type="Spring.Objects.TestObject, Spring.Core.Tests">                      
      <property name="age" value="21"/>
    </object>
  </property>          
</object>
        
// will result in 21, which is the value of property 'spouse.age' of object 'person'        
<object name="theAge" type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
  <property name="TargetObject" ref="person"/>
  <property name="TargetProperty" value="spouse.age"/>
</object>

An example of using a PropertyRetrievingFactoryObject to evaluate a static property is shown below.

<object id="cultureAware" 
        type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
  <property name="culture" ref="cultureFactory"/>
</object>

<object id="cultureFactory" 
        type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
  <property name="StaticProperty">
      <value>System.Globalization.CultureInfo.CurrentUICulture, Mscorlib</value>
  </property>
</object>

Similarly, an example showing the use of an instance property is shown below.

<object id="instancePropertyCultureAware" 
        type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
  <property name="Culture" ref="instancePropertyCultureFactory"/>
</object>

<object id="instancePropertyCultureFactory" 
        type="Spring.Objects.Factory.Config.PropertyRetrievingFactoryObject, Spring.Core">
  <property name="TargetObject" ref="instancePropertyCultureAwareSource"/>
  <property name="TargetProperty" value="MyDefaultCulture"/>
</object>

<object id="instancePropertyCultureAwareSource" 
        type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>
    

3.3.5.2. Setting a reference to the value of field.

The FieldRetrievingFactoryObject class addresses much the same area of concern as the PropertyRetrievingFactoryObject described in the previous section. However, as its name might suggest, the FieldRetrievingFactoryObject class is concerned with looking up the value of a public field exposed on either an instance or a class (and similarly, in the case of a field exposed on a class, the field must obviously be static).

The following example demonstrates using a FieldRetrievingFactoryObject to look up the value of a (public, static) field exposed on a class

<object id="withTypesField" 
        type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
  <property name="Types" ref="emptyTypesFactory"/>
</object>

<object id="emptyTypesFactory" 
        type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core">
  <property name="TargetType" value="System.Type, Mscorlib"/>
    <property name="TargetField" value="EmPTytypeS"/>
</object>
      

The example in the next section demonstrates the look up of a (public) field exposed on an object instance.

<object id="instanceCultureAware" 
        type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests">
  <property name="Culture" ref="instanceCultureFactory"/>
</object>

<object id="instanceCultureFactory"
  type="Spring.Objects.Factory.Config.FieldRetrievingFactoryObject, Spring.Core">
  <property name="TargetObject" ref="instanceCultureAwareSource"/>
  <property name="TargetField" value="Default"/>
</object>

<object id="instanceCultureAwareSource" 
         type="Spring.Objects.Factory.Xml.XmlObjectFactoryTests+MyTestObject, Spring.Core.Tests"/>
    

3.3.5.3. Setting a property or constructor argument to the return value of a method invocation.

The MethodInvokingFactoryObject rounds out the trio of classes that permit the setting of properties and constructor arguments using the members of other objects and classes. Whereas the PropertyRetrievingFactoryObject and FieldRetrievingFactoryObject classes dealt with simply looking looking up and returning the value of property or field on an object or class, the MethodInvokingFactoryObject allows one to set a constructor or property to the return value of an arbitrary method invocation,

The MethodInvokingFactoryObject class handles both the case of invoking an (instance) method on another object in the container, and the case of a static method call on an arbitrary class. Additonally, it is sometimes neccessary to invoke a method just to perform some sort of initialization.... while the mechanisms for handling object initialization have yet to be introduced (see Section 3.5.1.1, “IInitializingObject / init-method ”), these mechanisms do not permit any arguments to be passed to any initialization method, and are confined to invoking an initialization method on the object that has just been instantiated by the container. The MethodInvokingFactoryObject allows one to invoke pretty much any method on any object (or class in the case of a static method).

The following example (in an XML based IObjectFactory definition) uses the MethodInvokingFactoryObject class to force a call to a static factory method prior to the instantiation of the object...

<object id="force-init"
  type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
  <property name="StaticMethod">
    <value>ExampleNamespace.ExampleInitializerClass.Initialize</value>
  </property>
</object>
<object id="myService" depends-on="force-init"/>

Note that the definition for the myService object has used the depends-on attribute to refer to the force-init object, which will force the initialization of the force-init object first (and thus the calling of its configured StaticMethod static initializer method, when myService is first initialized. Please note that in order to effect this initialization, the MethodInvokingFactoryObject object must be operating in singleton mode (the default.. see the next paragraph).

Note that since this class is expected to be used primarily for accessing factory methods, this factory defaults to operating in singleton mode. As such, as soon as all of the properties for a MethodInvokingFactoryObject object have been set, and if the MethodInvokingFactoryObject object is still in singleton mode, the method will be invoked immediately and the return value cached for later access. The first request by the container for the factory to produce an object will cause the factory to return the cached return value for the current request (and all subsequent requests). The IsSingleton property may be set to false, to cause this factory to invoke the target method each time it is asked for an object (in this case there is obviously no caching of the return value).

A static target method may be specified by setting the targetMethod property to a string representing the static method name, with TargetType specifying the Type that the static method is defined on. Alternatively, a target instance method may be specified, by setting the TargetObject property to the name of another Spring.NET managed object definition (the target object), and the TargetMethod property to the name of the method to call on that target object.

Arguments for the method invocation may be specified in two ways (or even a mixture of both)... the first involves setting the Arguments property to the list of arguments for the method that is to be invoked. Note that the ordering of these arguments is significant... the order of the values passed to the Arguments property must be the same as the order of the arguments defined on the method signature, including the argumentType. This is shown in the example below

<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
  <property name="TargetType" value="Whatever.MyClassFactory, MyAssembly"/>
  <property name="TargetMethod" value="GetInstance"/>
  
  <!-- the ordering of arguments is significant -->
  <property name="Arguments">
    <list>
      <value>1st</value>
      <value>2nd</value>
      <value>and 3rd arguments</value>
      <!-- automatic Type-conversion will be performed prior to invoking the method -->
    </list>
  </property>
</object>

The second way involves passing an arguments dictionary to the NamedArguments property... this dictionary maps argument names (Strings) to argument values (any object). The argument names are not case-sensitive, and order is (obviously) not significant (since dictionaries by definition do not have an order). This is shown in the example below

<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
  <property name="TargetObject">
    <object type="Whatever.MyClassFactory, MyAssembly"/>
  </property>
  <property name="TargetMethod" value="Execute"/>
  
  <!-- the ordering of named arguments is not significant -->
  <property name="NamedArguments">
    <dictionary>
      <entry key="argumentName"><value>1st</value></entry>
      <entry key="finalArgumentName"><value>and 3rd arguments</value></entry>
      <entry key="anotherArgumentName"><value>2nd</value></entry>
    </dictionary>
  </property>
</object>

The following example shows how use MethodInvokingFactoryObject to call an instance method.

<object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />

<object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
  <property name="TargetObject" ref="myMethodObject"/>
  <property name="TargetMethod" value="Execute"/>
</object>

The above example could also have been written using an anonymous inner object definition... if the object on which the method is to be invoked is not going to be used outside of the factory object definition, then this is the preferred idiom because it limits the scope of the object on which the method is to be invoked to the surrounding factory object.

Finally, if you want to use MethodInvokingFactoryObject in conjunction with a method that has a variable length argument list, then please note that the variable arguments need to be passed (and configured) as a list. Let us consider the following method definition that uses the params keyword (in C#), and its attendant (XML) configuration...

[C#]
public class MyClassFactory
{
    public object CreateObject(Type objectType, params string[] arguments)
    {
        return ... // implementation elided for clarity...
    }
}

<object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
				
<object id="paramsMethodObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
  <property name="TargetObject" ref="myMethodObject"/>
  <property name="TargetMethod" value="CreateObject"/>
  <property name="Arguments">
    <list>
      <value>System.String</value>
      <!-- here is the 'params string[] arguments' -->
      <list>
        <value>1st</value>
        <value>2nd</value>
      </list>
    </list>
</object>

3.3.6. Additional IFactoryObject implementations

In addition to PropertyRetrievingFactoryObject, MethodInvokingFactoryObject, and FieldRetrievingFactoryObject Spring.NET comes with other useful implementations of the IFactoryObject interface. These are discussed below.

3.3.6.1. Log4Net

The Log4NetFactoryObject is useful when you would like to share a logging instance across a number of classes instead of creating a logging instance per class or class hierarchy. In the example shown below the same logging instance, with a log4Net name of "DAOLogger", is used in both the SimpleAccountDao and SimpleProducDao data access objects.

<objects xmlns="http://www.springframework.net" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://www.springframework.net
         http://www.springframework.net/xsd/spring-objects.xsd" >

    <object name="daoLogger" type="Spring.Objects.Factory.Config.Log4NetFactoryObject, Spring.Core">
      <property name="logName" value="DAOLogger"/>
    </object>
        
    <object name="productDao" type="PropPlayApp.SimpleProductDao, PropPlayApp ">
      <property name="maxResults" value="100"/>
      <property name="dbConnection" ref="myConnection"/>
      <property name="log" ref="daoLogger"/>
    </object>

    <object name="accountDao" type="PropPlayApp.SimpleAccountDao, PropPlayApp ">
      <property name="maxResults" value="100"/>
      <property name="dbConnection" ref="myConnection"/>
      <property name="log" ref="daoLogger"/>
    </object>
    
    <object name="myConnection" type="System.Data.Odbc.OdbcConnection, System.Data"> 
      <property name="connectionstring" value="dsn=MyDSN;uid=sa;pwd=myPassword;"/> 
    </object> 
    
</objects>

3.3.7. Using depends-on

Spring.NET uses the <ref/> element to express references to other dependant objects. Unless you have some special initialization requirements, you don't have to use the <depends-on/> element. However, when you are using statics that need initialization or some object needs to be initialized because of something else needing preparation, you can use the <depends-on/> element. This will ensure all objects you've listed as dependencies will get initialized before they're actually set on the object. For example...

<object id="objectOne" type="Examples.ExampleObject, ExamplesLibrary" depends-on="manager">
  <property name="manager" ref="manager"/>
</object>

<object id="manager" type="ManagerObject"/>

3.3.8. Autowiring collaborators

Spring.NET has autowire capabilities, meaning that it is possible to automatically let Spring.NET resolve collaborators (other objects) for your object by inspecting the object definitions in the container. Autowiring is specified per object and can thus be enabled for some objects, while other objects won't be autowired. Using autowiring, it is possible to reduce or even wholly eliminate the need to specify properties or constructor arguments. [2] The autowiring functionality has five modes...

Table 3.3. Autowiring modes

ModeExplanation
noNo autowiring at all. This is the default value and you are encouraged not to change this for large applications, since specifying your collaborators explicitly gives you a feeling for what you're actually doing (always a bonus) and is a great way of somewhat documenting the structure of your system.
byNameThis option will inspect the objects within the container, and look for an object named exactly the same as the property which needs to be autowired. For example, if you have an object definition that is set to autowire by name, and it contains a Master property, Spring.NET will look for an object definition named Master, and use it as the value of the Master property on your object definition.
byTypeThis option gives you the ability to resolve collaborators by type instead of by name. Supposing you have an IObjectDefinition with a collaborator typed SqlConnection, Spring.NET will search the entire object factory for an object definition of type SqlConnection and use it as the collaborator. If 0 (zero) or more than 1 (one) object definitions of the desired type exist in the container, a failure will be reported and you won't be able to use autowiring for that specific object.
constructorThis is analogous to byType, but applies to constructor arguments. If there isn't exactly one object of the constructor argument type in the object factory, a fatal error is raised.
autodetectChooses constructor or byType through introspection of the object class. If a default constructor is found, byType gets applied.

[Note]
Explicit dependencies always override autowiring. Autowire behavior can be combined with dependency checking, which will be performed after all autowiring has been completed.

3.3.9. Checking for dependencies

Spring.NET has the ability to try to check for the existence of unresolved dependencies of an object deployed into the container. These are properties of the object, which do not have actual values set for them in the object definition, or alternately provided automatically by the autowiring feature.

This feature is sometimes useful when you want to ensure that all properties (or all properties of a certain type) are set on an object. Of course, in many cases an object class will have default values for many properties, or some properties do not apply to all usage scenarios, so this feature is of limited use. Dependency checking can also be enabled and disabled per object, just as with the autowiring functionality. The default dependency checking mode is to not check dependencies. Dependency checking can be handled in several different modes. In XML-based configuration, this is specified via the dependency-check attribute in an object definition, which may have the following values.

Table 3.4. Dependency checking modes

ModeExplanation
noneNo dependency checking. Properties of the object which have no value specified for them are simply not set.
simpleDependency checking is done for primitive types and collections (this means everything except collaborators).
objectDependency checking is done for collaborators only.
allDependency checking is done for collaborators, primitive types and collections.

3.4. Type conversion

Type converters are responsible for converting objects from one type to another. When using the XML based file to configure the IoC container, string based property values are converted to the target property type. Spring will rely on the standard .NET support for type conversion unless an alternative TypeConverter is registered for a given type. How to register custom TypeConverters will be described shortly. As a reminder, the standard .NET type converter support works by associating a TypeConverter attribute with the class definition by passing the type of the converter as an attribute argument. [3] For example, an abbreviated class definition for the BCL type Font is shown below.

[Serializable, TypeConverter(typeof(FontConverter)), ...]
public sealed class Font : MarshalByRefObject, ICloneable, ISerializable, IDisposable
{
  // Methods
  
  ... etc ..
}

3.4.1. Type Conversion for Enumerations

The default type converter for enumerations is the System.ComponentModel.EnumConverter class. To specify the value for an enumerated property, simply use the name of the property. For example the TestObject class has a property of the enumerated type FileMode. One of the values for this enumeration is named Create. The following XML fragment shows how to configure this property

<object id="rod" type="Spring.Objects.TestObject, Spring.Core.Tests">
  <property name="name" value="Rod"/>
  <property name="FileMode" value="Create"/>
</object>

3.4.2. Built-in TypeConverters

Spring.NET pre-registers a number of custom TypeConverter instances (for example, to convert a type expressed as a string into a real System.Type object). Each of those is listed below and they are all located in the Spring.Objects.TypeConverters namespace of the Spring.Core library.

Table 3.5. Built-in TypeConverters

TypeExplanation
RuntimeTypeConverterParses strings representing System.Types to actual System.Types and the other way around.
FileInfoConverter Capable of resolving strings to a System.IO.FileInfo object.
StringArrayConverter Capable of resolving a comma-delimited list of strings to a string-array and vice versa.
UriConverter Capable of resolving a string representation of a URI to an actual URI-object.
FileInfoConverter Capable of resolving a string representation of a FileInfo to an actual FileInfo-object.
StreamConverter Capable of resolving Spring IResource URI (string) to its corresponding InputStream-object.
ResourceConverter Capable of resolving Spring IResource URI (string) to an IResource object.
ResourceManagerConverter Capable of resolving a two part string (resource name, assembly name) to a System.Resources.ResourceManager object.
RGBColorConverter Capable of resolving a comma separated list of Red, Green, Blue integer values to a System.Drawing.Color structure.
ExpressionConverter Capable of resolving a string into an instance of an object