575 lines
21 KiB
XML
575 lines
21 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter version="5" xml:id="codeconfig-attribute-reference"
|
|
xmlns="http://docbook.org/ns/docbook"
|
|
xmlns:ns5="http://www.w3.org/1998/Math/MathML"
|
|
xmlns:ns42="http://www.w3.org/2000/svg"
|
|
xmlns:ns4="http://www.w3.org/1999/xlink"
|
|
xmlns:ns3="http://www.w3.org/1999/xhtml"
|
|
xmlns:ns="http://docbook.org/ns/docbook">
|
|
<title>Attribute Reference</title>
|
|
|
|
<para>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.</para>
|
|
|
|
<sect1 xml:id="attribute-reference">
|
|
<title>[Configuration] Attribute</title>
|
|
|
|
<para>The <literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
attribute is applied to classes that contain one or more <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attributed-methods. During scanning by the
|
|
<literal>CodeConfigApplicationContext</literal>, only types having the
|
|
<literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
attribute will be considered candidates to contain Object Definition
|
|
configurations.</para>
|
|
|
|
<sect2>
|
|
<title>Using the Configuration Attribute</title>
|
|
|
|
<para></para>
|
|
|
|
<sect3>
|
|
<title>Simple Usage</title>
|
|
|
|
<para>The most common usage of the <literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
attribute simply applies the attribute to a class without any
|
|
attribute parameters. The name of the of the type, once registered
|
|
with the <literal>CodeConfigApplicationContext</literal>, 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.<programlisting
|
|
language="csharp">[Configuration]
|
|
public class MyConfigurationClass
|
|
{
|
|
//[ObjectDef] methods here
|
|
}</programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Controlling the Name of the Configuration Class</title>
|
|
|
|
<para>While not a common use-case, if you need fine-grained control
|
|
over the name of the type registered with the
|
|
<literal>CodeConfigApplicationContext</literal>, the <literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
attribute accepts a <literal>Name</literal> parameter which will be
|
|
applied to the registered Object Definition in the
|
|
<literal>CodeConfigApplicationContext</literal>.<programlisting
|
|
language="csharp">[Configuration("MySpecialConfigurationClass")]
|
|
public class MyConfigurationClass
|
|
{
|
|
//[ObjectDef] methods here
|
|
}</programlisting></para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="objectdef-attribute-reference">
|
|
<title>[ObjectDef] Attribute</title>
|
|
|
|
<para>The <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attribute is applied to one or more methods within any class to which the
|
|
<literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
attribute has been applied. During scanning, any <literal>public
|
|
virtual</literal> method having the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attribute is considered to contain Object Definition metadata.</para>
|
|
|
|
<sect2>
|
|
<title>Using the ObjectDef Attribute</title>
|
|
|
|
<para></para>
|
|
|
|
<sect3>
|
|
<title>Simple Usage</title>
|
|
|
|
<para>The first usage of the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attribute simply applies the attribute to the method. The name of the
|
|
of the Object to be registered with the
|
|
<literal>CodeConfigApplicationContext</literal>, will be the name of
|
|
the method itself.<programlisting language="csharp">[Configuration]
|
|
public class MyConfigurationClass
|
|
{
|
|
[ObjectDef]
|
|
public virtual HomeController HomeController()
|
|
{
|
|
return new HomeController();
|
|
}
|
|
}</programlisting></para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Controlling the Name and Aliases of the Defined Object</title>
|
|
|
|
<para>If you need to control the name of the Object registered with
|
|
the <literal>CodeConfigApplicationContext</literal>, the
|
|
<literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attribute accepts one or more comma-delimited names as aliases for the
|
|
Object when registered.</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Setting an Init Method for the Object</title>
|
|
|
|
<para>If you need to declare an Initialization Method for the object
|
|
definition, the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attribute accepts a method name to be invoked at the appropriate stage
|
|
in the object's creation by the
|
|
<literal>CodeConfigApplicationContext</literal>.</para>
|
|
|
|
<programlisting language="csharp">[Configuration]
|
|
public class MyConfigurationClass
|
|
{
|
|
[ObjectDef(InitMethod="AfterCreation")] //assumes a public method on the HomeController type named 'AfterCreation()'
|
|
public virtual HomeController HomeController()
|
|
{
|
|
return new HomeController();
|
|
}
|
|
}</programlisting>
|
|
|
|
<para><note>
|
|
<para>You can just also call the method 'AfterCreation' inside the
|
|
body of the HomeController implementation itself.</para>
|
|
</note></para>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Setting a Destroy Method for the Object</title>
|
|
|
|
<para>If you need to declare a Destroy Method for the object
|
|
definition, the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
attribute accepts a method name to be invoked at the appropriate stage
|
|
in the object's destruction by the
|
|
<literal>CodeConfigApplicationContext</literal>.</para>
|
|
|
|
<programlisting language="csharp">[Configuration]
|
|
public class MyConfigurationClass
|
|
{
|
|
[ObjectDef(DestroyMethod="CleanupResources")] //assumes a public method on the HomeController type named 'CleanupResources()'
|
|
public virtual HomeController HomeController()
|
|
{
|
|
return new HomeController();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="dependson-attribute-reference">
|
|
<title>[DependsOn] Attribute</title>
|
|
|
|
<para>The <literal>[DependsOn]</literal> attribute can be applied to any
|
|
<literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>-attributed
|
|
method to declare a construction sequence dependency upon one or more
|
|
objects that the <literal>CodeConfigApplicationContext</literal> 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.</para>
|
|
|
|
<sect2>
|
|
<title>Using the DependsOn Attribute</title>
|
|
|
|
<para></para>
|
|
|
|
<sect3>
|
|
<title>Controlling Creation Dependencies</title>
|
|
|
|
<para>The <literal>[DependsOn]</literal> attribute accepts one or more
|
|
comma-delimited strings representing the names of the objects upon
|
|
which the current object will depend.</para>
|
|
|
|
<programlisting language="csharp">[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
|
|
}</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="import-attribute-reference">
|
|
<title>[Import] Attribute</title>
|
|
|
|
<para>The <literal>[Import]</literal> attribute allows you to identify one
|
|
or more additional types that will also be scanned when the current type
|
|
is scanned.</para>
|
|
|
|
<sect2>
|
|
<title>Using the Import Attribute</title>
|
|
|
|
<para></para>
|
|
|
|
<sect3>
|
|
<title>Specifying Additional Types to Scan</title>
|
|
|
|
<para>To support your specifying additional types to scan, the
|
|
<literal>[Import]</literal> 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 <literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
attribute applied to them. Note that no error is reported if these
|
|
types lack the<literal>[Configuration</literal>] attribute, but
|
|
without it they will not satisfy the scanner's requirements for
|
|
Configuration candidates.</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Chaining [Import] Directives</title>
|
|
|
|
<para>Types pointed to by one <literal>[Import]</literal> attribute
|
|
may in turn have their own <literal>[Import]</literal> 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 <literal>[Import]</literal> attribute to
|
|
'chain' successive types into the scanning scope, transitively
|
|
pointing from one <literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>-attributed
|
|
type to the next as in the following example where
|
|
<literal>MyConfigurationClass</literal> has an
|
|
<literal>[Import]</literal> attribute pointing to the
|
|
<literal>MySecondConfiguration</literal> class which in turn has an
|
|
<literal>[Import</literal>] attribute pointing to the
|
|
<literal>MyThirdConfiguration</literal> class.</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
|
|
<para>Given this series of transitive or 'chained'
|
|
<literal>[Import]</literal>attributes, the
|
|
<literal>CodeConfigApplicationContext</literal> would only need to be
|
|
told to scan the single <literal>MyConfigurationClass</literal> type
|
|
in order to effectively scan and discover the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
methods contained all three <literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
types. Using this approach, its possible to use a compositional
|
|
approach to segregate <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
methods into multiple<literal> <link
|
|
linkend="configuration-attribute-reference">[Configuration]</link></literal>
|
|
classes and then chain them together just as one might do with XML
|
|
based configuration files for many of the other
|
|
<literal>IApplicationContext</literal> implementations.</para>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="importresource-attribute-reference">
|
|
<title>[ImportResource] Attribute</title>
|
|
|
|
<para>Just as the <literal>[Import]</literal> attribute provides the
|
|
ability to reference and import additional types attributed with the
|
|
<literal><link
|
|
linkend="configuration-attribute-reference">[Configuration]</link>
|
|
</literal>attribute, the <literal>[ImportResrource]</literal> attribute
|
|
permits referencing and importing Object Defintions from any
|
|
<literal>IResource</literal> implementation including those defined
|
|
natively in Spring.NET ("<literal>file://</literal>",
|
|
"<literal>assembly://</literal>", etc.).</para>
|
|
|
|
<sect2>
|
|
<title>Using the ImportResourceAttribute</title>
|
|
|
|
<para></para>
|
|
|
|
<sect3>
|
|
<title>Specifying an IResource</title>
|
|
|
|
<para>To import an <literal>IResource</literal>, simply reference its
|
|
path in the <literal>[ImportResource]</literal> attribute. In the
|
|
following example, the embedded assembly resource
|
|
<literal>ObjectDefinitions.xml</literal> is being imported into the
|
|
process of scanning and parsing the
|
|
<literal>MyConfigurationClass</literal> type. This makes all of the
|
|
object definitions present in the embedded
|
|
<literal>ObjectDefinitions.xml</literal> file available to the
|
|
<literal>CodeConfigApplicationContext</literal> as it builds its
|
|
Object Defintions.</para>
|
|
|
|
<programlisting language="csharp">[Configuration]
|
|
[ImportResource("assembly://MyApplication.Config/MyCompany.MyApplication.Config/ObjectDefinitions.xml")]
|
|
public class MyConfigurationClass
|
|
{
|
|
[ObjectDef]
|
|
public virtual HomeController HomeController()
|
|
{
|
|
return new HomeController();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Specifying Multiple IResources</title>
|
|
|
|
<para>To import multiple <literal>IResource</literal>s, simply provide
|
|
multiple <literal>[ImportResource] </literal>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.</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Specifying a specific IObjectDefintionReader to Parse the
|
|
IResource</title>
|
|
|
|
<para>By default, the<literal> [ImportResource]</literal> attribute
|
|
will use the Spring.NET provided
|
|
<literal>XmlObjectDefinitionReader</literal> to parse the imported
|
|
<literal>IResource</literal>. If your imported resource cannot be
|
|
parsed with the <literal>XmlObjectDefinitionReader</literal> then you
|
|
can provide the type of the specific implementation of
|
|
<literal>IObjectDefinitionReader</literal> that the<literal>
|
|
[ImportResource]</literal> process should use. Note that this provided
|
|
type must implement the <literal>IObjectDefinitionReader</literal>
|
|
interface or an Exception will be thrown when the
|
|
<literal>[ImportResource]</literal> attribute is evaluated.</para>
|
|
|
|
<programlisting language="csharp">[Configuration]
|
|
[ImportResource("assembly://MyApplication.Config/MyCompany.MyApplication.Config/ObjectDefinitions.CSV", DefinitionReader = typeof(MyCommaSeparatedValueObjectDefinitionReader))]
|
|
public class MyConfigurationClass
|
|
{
|
|
[ObjectDef]
|
|
public virtual HomeController HomeController()
|
|
{
|
|
return new HomeController();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="lazy-attribute-reference">
|
|
<title>[Lazy] Attribute</title>
|
|
|
|
<para>The <literal>[Lazy]</literal> attribute allows you to specify that
|
|
the object described by the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
should either be be lazily or eagerly instantiated.</para>
|
|
|
|
<sect2>
|
|
<title>Using the Lazy Attribute</title>
|
|
|
|
<para></para>
|
|
|
|
<sect3>
|
|
<title>Specifying Lazy Instantiation</title>
|
|
|
|
<para>To specify Lazy Instantiation of any singleton object by the
|
|
<literal>CodeConfigApplicationContext</literal>, apply the<literal>
|
|
[Lazy] </literal>attribute to any <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>-attributed
|
|
method as in the following example. Note that the default usage of
|
|
the<literal>[Lazy]</literal> attribute sets Lazy = true and so
|
|
<literal>[Lazy]</literal> and <literal>[Lazy(true)]</literal> are
|
|
considered functionally equivalent. Also note that specification of
|
|
lazy instantiation is only valid for Singleton-scoped objects; any
|
|
attempt to apply the <literal>[Lazy]</literal> attribute to a
|
|
non-singleton-scoped <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>
|
|
method will result in an exception thrown by the underlying
|
|
ApplicationContext.</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
|
|
<sect3>
|
|
<title>Specifying Non-Lazy (eager) Instantiation</title>
|
|
|
|
<para>As the default instantiation behavior for the
|
|
<literal>CodeConfigApplicationContext</literal> is to perform eager
|
|
instantiation, no special attribute needs to be applied to achieve
|
|
eager instantiation of the object. However, the
|
|
<literal>[Lazy]</literal> attribute will accept a
|
|
<literal>bool</literal> value of <literal>false</literal> if you
|
|
desire to be explicit about the <literal>[Lazy]</literal> setting for
|
|
the <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link>
|
|
</literal>as shown in the following code snippet.</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
</sect3>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 xml:id="scope-attribute-reference">
|
|
<title>[Scope] Attribute</title>
|
|
|
|
<para>The [Scope] attribute permits you to declare the lifetime of the
|
|
object managed by the <literal>CodeConfigApplicationContext</literal> for
|
|
each <literal><link
|
|
linkend="objectdef-attribute-reference">[ObjectDef]</link></literal>-attributed
|
|
method.</para>
|
|
|
|
<sect2>
|
|
<title>Scope Attribute Usage</title>
|
|
|
|
<para>The <literal>[Scope]</literal> attribute accepts a single
|
|
<literal>ObjectScope</literal> <literal>enum</literal> argument as
|
|
defined by Spring.NET and demonstrated in the following snippet:</para>
|
|
|
|
<programlisting language="csharp">[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();
|
|
}
|
|
}</programlisting>
|
|
</sect2>
|
|
</sect1>
|
|
</chapter>
|