# Attribute Reference

In this chapter, we will explore the attributes that are the essential components for declaring Object Definitions with Spring CodeConfig. These attributes have a corresponding representation in Spring XML so should be very familiar to current Spring.NET users.

## [Configuration] Attribute

The `[Configuration]` attribute is applied to classes that contain one or more `[ObjectDef]` attributed-methods. During scanning by the `CodeConfigApplicationContext`, only types having the `[Configuration]` attribute will be considered candidates to contain Object Definition configurations.

### Using the Configuration Attribute

#### Simple Usage

The most common usage of the `[Configuration]` attribute simply applies the attribute to a class without any attribute parameters. The name of the of the type, once registered with the `CodeConfigApplicationContext`, will be the name of the class itself. Note that it is not a common use-case to ask the container for this configuration class.

    [Configuration]
    public class MyConfigurationClass
    {
      //[ObjectDef] methods here
    }

#### Controlling the Name of the Configuration Class

While not a common use-case, if you need fine-grained control over the name of the type registered with the `CodeConfigApplicationContext`, the `[Configuration]` attribute accepts a `Name` parameter which will be applied to the registered Object Definition in the `CodeConfigApplicationContext`.

    [Configuration("MySpecialConfigurationClass")]
    public class MyConfigurationClass
    {
      //[ObjectDef] methods here
    }

## [ObjectDef] Attribute

The `[ObjectDef]` attribute is applied to one or more methods within any class to which the `[Configuration]` attribute has been applied. During scanning, any `public virtual` method having the `[ObjectDef]` attribute is considered to contain Object Definition metadata.

### Using the ObjectDef Attribute

#### Simple Usage

The first usage of the `[ObjectDef]` attribute simply applies the attribute to the method. The name of the of the Object to be registered with the `CodeConfigApplicationContext`, will be the name of the method itself.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

#### Controlling the Name and Aliases of the Defined Object

If you need to control the name of the Object registered with the `CodeConfigApplicationContext`, the `[ObjectDef]` attribute accepts one or more comma-delimited names as aliases for the Object when registered.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef(Names="TheHomeController")]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }

      [ObjectDef(Names="TheSpecialNameForAboutController,AliasForAboutController")]
      public virtual AboutController AboutController()
      {
        return new AboutController();
      }
    }

#### Setting an Init Method for the Object

If you need to declare an Initialization Method for the object definition, the `[ObjectDef]` attribute accepts a method name to be invoked at the appropriate stage in the object's creation by the `CodeConfigApplicationContext`.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef(InitMethod="AfterCreation")] //assumes a public method on the HomeController type named 'AfterCreation()'
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

You can just also call the method 'AfterCreation' inside the body of the HomeController implementation itself.

#### Setting a Destroy Method for the Object

If you need to declare a Destroy Method for the object definition, the `[ObjectDef]` attribute accepts a method name to be invoked at the appropriate stage in the object's destruction by the `CodeConfigApplicationContext`.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef(DestroyMethod="CleanupResources")] //assumes a public method on the HomeController type named 'CleanupResources()'
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

## [DependsOn] Attribute

The `[DependsOn]` attribute can be applied to any `[ObjectDef]`-attributed method to declare a construction sequence dependency upon one or more objects that the `CodeConfigApplicationContext` will ensure are created prior to the creation of the current object. This is only required if there is a hidden depedency between the two classes that isn't exposed via constructor or setter properties.

### Using the DependsOn Attribute

#### Controlling Creation Dependencies

The `[DependsOn]` attribute accepts one or more comma-delimited strings representing the names of the objects upon which the current object will depend.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef]
      [DependsOn("Dependency1")] //HomeController requires "Dependency1" to be created first
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }

      [ObjectDef]
      [DependsOn("Dependency1", "Dependency2")] //AboutController requires "Dependency1" and "Dependency2" to be created first
      public virtual AboutController AboutController()
      {
        return new AboutController();
      }b
    }

## [Import] Attribute

The `[Import]` attribute allows you to identify one or more additional types that will also be scanned when the current type is scanned.

### Using the Import Attribute

#### Specifying Additional Types to Scan

To support your specifying additional types to scan, the `[Import]` attribute accepts one or more comman-delimited Types to scan as well. To be candidates for scanning, the types listed in this array must also have the `[Configuration]` attribute applied to them. Note that no error is reported if these types lack the`[Configuration`] attribute, but without it they will not satisfy the scanner's requirements for Configuration candidates.

    [Configuration]
    [Import(typeof(MySecondConfiguration), typeof(MyThirdConfiguration))]
    public class MyConfigurationClass
    {
      [ObjectDef]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

    [Configuration]
    public class MySecondConfiguration
    {
      [ObjectDef]
      public virtual AboutController AboutController()
      {
        return new AboutController();
      }
    }

    [Configuration]
    public class MyThirdConfiguration
    {
      [ObjectDef]
      public virtual SomeOtherController SomeOtherController()
      {
        return new SomeOtherController();
      }
    }

#### Chaining [Import] Directives

Types pointed to by one `[Import]` attribute may in turn have their own `[Import]` attributes pointing to yet more types to scan. Using this approach, its possible to specify perhaps only a single 'root' class from which to 'begin' the scan and leverage the `[Import]` attribute to 'chain' successive types into the scanning scope, transitively pointing from one `[Configuration]`-attributed type to the next as in the following example where `MyConfigurationClass` has an `[Import]` attribute pointing to the `MySecondConfiguration` class which in turn has an `[Import`] attribute pointing to the `MyThirdConfiguration` class.

    [Configuration]
    [Import(typeof(MySecondConfiguration))]
    public class MyConfigurationClass
    {
      [ObjectDef]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

    [Configuration]
    [Import(typeof(MyThirdConfiguration))]
    public class MySecondConfiguration
    {
      [ObjectDef]
      public virtual AboutController AboutController()
      {
        return new AboutController();
      }
    }

    [Configuration]
    public class MyThirdConfiguration
    {
      [ObjectDef]
      public virtual SomeOtherController SomeOtherController()
      {
        return new SomeOtherController();
      }
    }

Given this series of transitive or 'chained' `[Import]`attributes, the `CodeConfigApplicationContext` would only need to be told to scan the single `MyConfigurationClass` type in order to effectively scan and discover the `[ObjectDef]` methods contained all three `[Configuration]` types. Using this approach, its possible to use a compositional approach to segregate `[ObjectDef]` methods into multiple`[Configuration]` classes and then chain them together just as one might do with XML based configuration files for many of the other `IApplicationContext` implementations.

## [ImportResource] Attribute

Just as the `[Import]` attribute provides the ability to reference and import additional types attributed with the `[Configuration]` attribute, the `[ImportResrource]` attribute permits referencing and importing Object Defintions from any `IResource` implementation including those defined natively in Spring.NET ("`file://`", "`assembly://`", etc.).

### Using the ImportResourceAttribute

#### Specifying an IResource

To import an `IResource`, simply reference its path in the `[ImportResource]` attribute. In the following example, the embedded assembly resource `ObjectDefinitions.xml` is being imported into the process of scanning and parsing the `MyConfigurationClass` type. This makes all of the object definitions present in the embedded `ObjectDefinitions.xml` file available to the `CodeConfigApplicationContext` as it builds its Object Defintions.

    [Configuration]
    [ImportResource("assembly://MyApplication.Config/MyCompany.MyApplication.Config/ObjectDefinitions.xml")]
    public class MyConfigurationClass
    {
      [ObjectDef]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

#### Specifying Multiple IResources

To import multiple `IResource`s, simply provide multiple `[ImportResource]` attributes, each with the single resource to import. The following example demonstrates importing an embedded assembly resource as well as two XML files on disk.

    [Configuration]
    [ImportResource("assembly://MyApplication.Config/MyCompany.MyApplication.Config/ObjectDefinitions.xml")]
    [ImportResource("file://ServiceObjectDefinitions.xml")]
    [ImportResource("file://c:/MySpecialConfigLocation/Deployment/SiteB/RepositoryObjectDefinitions.xml")]
    public class MyConfigurationClass
    {
      [ObjectDef]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

#### Specifying a specific IObjectDefintionReader to Parse the IResource

By default, the`[ImportResource]` attribute will use the Spring.NET provided `XmlObjectDefinitionReader` to parse the imported `IResource`. If your imported resource cannot be parsed with the `XmlObjectDefinitionReader` then you can provide the type of the specific implementation of `IObjectDefinitionReader` that the`[ImportResource]` process should use. Note that this provided type must implement the `IObjectDefinitionReader` interface or an Exception will be thrown when the `[ImportResource]` attribute is evaluated.

    [Configuration]
    [ImportResource("assembly://MyApplication.Config/MyCompany.MyApplication.Config/ObjectDefinitions.CSV", DefinitionReader = typeof(MyCommaSeparatedValueObjectDefinitionReader))]
    public class MyConfigurationClass
    {
      [ObjectDef]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

## [Lazy] Attribute

The `[Lazy]` attribute allows you to specify that the object described by the `[ObjectDef]` should either be be lazily or eagerly instantiated.

### Using the Lazy Attribute

#### Specifying Lazy Instantiation

To specify Lazy Instantiation of any singleton object by the `CodeConfigApplicationContext`, apply the`[Lazy]` attribute to any `[ObjectDef]`-attributed method as in the following example. Note that the default usage of the`[Lazy]` attribute sets Lazy = true and so `[Lazy]` and `[Lazy(true)]` are considered functionally equivalent. Also note that specification of lazy instantiation is only valid for Singleton-scoped objects; any attempt to apply the `[Lazy]` attribute to a non-singleton-scoped `[ObjectDef]` method will result in an exception thrown by the underlying ApplicationContext.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef]
      [Lazy] //functionally equivalent to [Lazy(true)]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }

      [ObjectDef]
      [Lazy] //invalid here because the scope is non-Singleton
      [Scope(ObjectScope.Prototype)]
      public virtual InvalidController InvalidController()
      {
        return new InvalidController();
      }
    }

#### Specifying Non-Lazy (eager) Instantiation

As the default instantiation behavior for the `CodeConfigApplicationContext` is to perform eager instantiation, no special attribute needs to be applied to achieve eager instantiation of the object. However, the `[Lazy]` attribute will accept a `bool` value of `false` if you desire to be explicit about the `[Lazy]` setting for the `[ObjectDef]` as shown in the following code snippet.

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef]
      [Lazy(false)] //functionally equivalent to simply not applying the [Lazy] attribute at all
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }
    }

## [Scope] Attribute

The [Scope] attribute permits you to declare the lifetime of the object managed by the `CodeConfigApplicationContext` for each `[ObjectDef]`-attributed method.

### Scope Attribute Usage

The `[Scope]` attribute accepts a single `ObjectScope` `enum` argument as defined by Spring.NET and demonstrated in the following snippet:

    [Configuration]
    public class MyConfigurationClass
    {
      [ObjectDef]
      [Scope(ObjectScope.Prototype)]
      public virtual HomeController HomeController()
      {
        return new HomeController();
      }

      [ObjectDef]
      [Scope(ObjectScope.Singleton)] //technically redundant since all types default to Singleton ObjectScope
      public virtual CustomerRepository CustomerRepository()
      {
        return new CustomerRepository();
      }

      [ObjectDef]
      [Scope(ObjectScope.Session)]
      public virtual UserSettings UserSettings()
      {
        return new UserSettings();
      }
    }