diff --git a/doc/reference/src/codeconfig-attribute-reference.xml b/doc/reference/src/codeconfig-attribute-reference.xml
new file mode 100644
index 00000000..2d6fcf5b
--- /dev/null
+++ b/doc/reference/src/codeconfig-attribute-reference.xml
@@ -0,0 +1,574 @@
+
+
+ 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 IResources, 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
+ ObjectScopeenum 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();
+ }
+}
+
+
+
diff --git a/doc/reference/src/codeconfig-context.xml b/doc/reference/src/codeconfig-context.xml
new file mode 100644
index 00000000..723b3b35
--- /dev/null
+++ b/doc/reference/src/codeconfig-context.xml
@@ -0,0 +1,536 @@
+
+
+ CodeConfigApplicationContext Reference
+
+ The CodeConfigApplicationContext is an
+ implementation of IApplicationContext designed to gather
+ its configuration from code-based sources as opposed to XML-based sources as
+ is the common case with most other IApplicationContext
+ implementations provided by Spring.NET.
+
+ This chapter introduces the CodeConfigApplicationContext and how you
+ can use .NET code to configure the Spring.NET container instead of XML
+ files. For a general overview on the design of the Spring.NET container
+ please see container
+ overview. The distribution includes three sample applications, two
+ console applications (the familiar MovieFinder and a prime number generator)
+ and a ASP.NET MVC web application. Refer to the examples section for more information.
+
+
+ The code-based configuration support requires .NET 2.0 or higher and
+ solutions that depend upon CodeConfig must be compiled with Visual Studio
+ 2008 or later.
+
+
+
+ Concepts
+
+ Internally, Spring.NET has a metadata model around the classes it is
+ responsible for managing, the main abstraction in this metadata model is
+ the interface IObjectDefinition. The
+ IObjectDefinition serves as the 'recipie'
+ that Spring.NET uses to perform dependency injection. In the case of
+ XML-based configuration sources, XmlApplicationContext parses XML files to
+ populate the metadata model. In the case of CodeConfig, the
+ CodeConfigApplicationContext scans one or more
+ assemblies containing one or more types attributed with the [Configuration]
+ attribute, parses them to construct appropriate
+ ObjectDefinition instances, and registers those Object
+ Definitions with the IApplicationContext for use. You
+ can also mix-and-match configuration sources, with some object definitions
+ originating in XML and others in code.
+
+
+ Using the CodeConfigApplicationContext
+
+ The CodeConfigApplicationContext usage pattern
+ consists of the following high-level steps:
+
+
+
+ Instantiate an instance of the
+ CodeConfigApplicationContext
+
+
+
+ [optional] Provide one ore more filtering
+ constraints to control the Assemblies and/or Types to participate in
+ the scanning
+
+
+
+ Perform the actual scanning
+
+
+
+ Initialize (refresh) the
+ CodeConfigApplicationContext which creates the
+ object definition and eagerly instantiates singleton objects.
+
+
+
+
+
+ Mixing and matching configuration metadata formats
+
+ You can also use a combination of XML and Code base configuration metadata to configure
+ the Spring.NET container. If you are an existing user of Spring.NET, incrementally adopting
+ the code base configuration model will be a common use-case. In this scenario you should use
+ the component-scan XML namespace to reference configuration metadata. Using the
+ component-scan namespace requires you to register a custom namespace parser in App.config.
+ Below is an example showing the use of the code config namespace
+
+ <objects xmlns="http://www.springframework.net"
+ xmlns:context="http://www.springframework.net/context">
+
+ <context:component-scan base-assemblies=""/>
+
+ <!-- <object/> definitions here -->
+
+
+</objects>
+
+
+ The base-assemblies attribute allows you to express limitations
+ of Assemblies to scan via a comma seperated list of assembly names.
+ The filter is a StartsWith filter
+
+ You will also need to configure the context namespace parser in
+ the main .NET application configuraiton file as shown below
+
+ <configuration>
+
+ <configSections>
+ <sectionGroup name="spring">
+ <!-- other Spring config sections handler like context, typeAliases, etc not shown for brevity -->
+ <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
+ </sectionGroup>
+ </configSections>
+
+ <spring>
+ <parsers>
+ <parser type="Spring.Context.Config.ContextNamespaceParser, Spring.Core.Configuration" />
+ </parsers>
+ </spring>
+
+</configuration>
+
+
+
+ You can also start from a CodeConfig class and import XML based
+ object defintions. The example below shows loading of an embedded XML
+ resource file using the [ImportResource]
+ attribute.
+
+ [Configuration]
+[ImportResource("assembly://MyApp/MyApp.MyNamespace.MyConfig/ObjectDefinitions.xml"))]
+public class DataModuleConfigurationClass
+{
+ [ObjectDef]
+ public virtual SomeType SomeType()
+ {
+ return new SomeType();
+ }
+}
+
+
+
+
+ Scanning Basics
+
+ The behavior of the CodeConfigApplicationContext
+ scanning operation can be controlled by the following constraints:
+
+
+
+ Assembly Inclusion Constraint
+
+ Only assemblies matching this contraint will be scanned;
+ defaults to 'all assemblies'.
+
+
+
+
+
+ Type Inclusion Contraint
+
+ Only types matching this contraint in assemblies matching the
+ Assembly Inclusion Constraint will be scanned;
+ defaults to 'all types'.
+
+
+
+
+ Scaning all assemblies
+
+ The simplest way to get started using code-based configuration is
+ to instruct the context to scan all assemblies, as shown below
+
+ var ctx = new CodeConfigApplicationContext();
+ctx.ScanAllAssemblies();
+ctx.Refresh();
+
+
+ Despite the name of the method 'ScanAllAssemblies', not all
+ assemblies need to be scanned for [Configuraiton] attributes. There is
+ an implicit filter that exclude the .NET BCL libraries as well as the
+ Spring.NET assemblies since these will never contain any
+ [Configuration] attributed classes. The name 'ScanAllAssemblies'
+ should be interpreted as scanning all of the other assemblies you
+ reference in your application.
+
+
+
+
+ Scanning specific assemblies and types
+
+ While the scanning process is very rapid (as compared to the
+ overhead of parsing XML files) you may want to control the scope of the
+ scanning operations to match your deployment or other usage models. To
+ facilitate control of the scope of the scanning operation, the
+ CodeConfigApplicationContext provides several
+ .ScanXXX() methods that accept constraints to be
+ applied to the assemblies and types during the scanning process. The
+ format of these constraints is that of
+ Predicate<T> where T is
+ either System.Reflection.Assembly or
+ System.Type, respectively. Recall that
+ Predicate<T> is any method that accepts a
+ single parameter of Type T and returns a
+ bool.
+
+ The list of scan methods and brief description is shown
+ below
+
+
+ Description
+
+
+
+
+ ScanAllAssemblies()
+
+ Scans all assemblies, except those in the .NET BCL and
+ Spring distribution
+
+
+
+ ScanWithTypeFilter(Predicate<Type>
+ typePredicate)
+
+ Scans only those types that match the
+ typePredicate
+
+
+
+ ScanWithAssemblyFilter(Predicate<Assembly>
+ assemblyPredicate)
+
+ Scans only those assemblines that match the
+ assemblyPredicate
+
+
+
+ Scan(Predicate<Assembly>
+ assemblyPredicate, Predicate<Type>
+ typePredicate)
+
+ Scans the AppDomain root path for assemblies that match
+ the assemblyPredicate and types that match
+ the typePredicate
+
+
+
+ Scan(AssemblyObjectDefinitionScanner
+ scanner)
+
+ Performs the scan using the settings encapsulated in the
+ provided ObjectDefintionScanner
+
+
+
+
+
+ Other sections below provide a more detailed description and usage
+ examples for the scan methods.
+
+ Note that as with any Predicate<T>
+ construct, the Predicate<Assembly> and
+ Predicate<Type> constraints may be of arbitrary
+ complexity, formulated using any combination of standard C# AND
+ (&&), OR (||), and NOT
+ (!) operators.
+
+ The following example matches assemblies with names containing
+ "Config" but NOT containing "Configuration" OR containing
+ "Services":
+
+ var ctx = new CodeConfigApplicationContext();
+ctx.ScanWithAssemblyFilter(assy => (assy.Name.FullName.Contains("Config") && !assy.Name.FullName.Contains("Configuration")) || assy.Name.FullName.Contains("Services");
+
+ Because its merely a .NET delegate, note that it is also possible
+ to pass any arbitrary method that satisfies the contract
+ (Predicate<T>), so assuming that the method
+ IsOneOfOurConfigAssemblies is defined elsewhere as
+ follows...
+
+ private bool IsOneOfOurConfigAssemblies(Assembly assy)
+{
+ return (assy.Name.FullName.Contains("Config") && !assy.Name.FullName.Contains("Configuration")) || assy.Name.FullName.Contains("Services");
+};
+
+ ...its possible to express the constraint in the call to
+ .Scan(...) much more succinctly as follows:
+
+ var ctx = new CodeConfigApplicationContext();
+ctx.ScanWithAssemblyFilter(IsOneOfOurConfigAssemblies);
+
+ None of this is anything other than simple .NET Delegate handling,
+ but its important to take note that the full flexibility of .NET
+ Delegates and lambda expressions is at your disposal for formulating and
+ passing scanning constraints.
+
+
+
+ Assembly Inclusion Constraints
+
+ To facilitate limiting the scope of scanning at the Assembly
+ level, the CodeConfigApplicationContext provides
+ several .ScanXXX() method signatures that accept a
+ constraint to be applied to the assemblies at scan time. The format of
+ this constraint matches
+ Predicate<System.Reflection.Assembly> (e.g. any
+ delegate method that accepts a single
+ System.Reflection.Assembly param and returns a
+ bool).
+
+ As an example, the following snippet demonstrates the invocation
+ of the scanning operation such that it will only scan assemblies whose
+ filename begins with the string
+ "MyCompany.MyApplication.Config." and so would match
+ assemblies like
+ MyCompany.MyApplication.Config.Services.dll and
+ MyCompany.MyApplication.Config.Infrastructure.dll but
+ would not match an assembly named
+ MyCompany.MyApplication.Core.dll.var ctx = new CodeConfigApplicationContext();
+ctx.ScanWithAssemblyFilter(assy => assy.Name.FullName.StartsWith("MyCompany.MyApplication.Config."));Because
+ the Predicate<System.Reflection.Assembly> has
+ access to the full reflection metadata of each assembly, it is also
+ possible to indicate assemblies to scan based on properties of one or
+ more contained types as in the following example that will scan any
+ assembly that contains at least one Type whose name
+ ends in "Config". Note that even though this
+ constraint is dependent upon Type metadata, it is
+ still a functional Assembly contraint, resulting in
+ filtering only at the Assembly level.
+
+ var ctx = new CodeConfigApplicationContext();
+ctx.ScanWithAssemblyFilter(a => a.GetTypes().Any(assy => assy.GetTypes().Any(type => type.FullName.EndsWith("Config"))));
+
+
+
+ Type Inclusion Constraints
+
+ To limit the scope of scanning of types within assemblies, the
+ CodeConfigApplicationContext provides several
+ .ScanXXX() method signatures that accept a constraint
+ to be applied to include types within assemblies at scan time. The
+ format of this contraint matches
+ Predicate<System.Type> (e.g. any delegate
+ method that accepts a single System.Type param and
+ returns a bool).
+
+ As an example, the following snippet demonstrates the invocation
+ of the scanning operation such that it will only scan types whose names
+ contain the string "Config" and so would match types named
+ "MyConfiguration",
+ "ServicesConfiguration", and
+ "ConfigurationSettings" but not
+ "MyClass".
+
+ var ctx = new CodeConfigApplicationContext();
+ctx.ScanWithTypeFilter(type => type.FullName.Contains("Config");
+
+ There are two important aspects to take note of in re: the
+ behavior of the CodeConfigApplicationContext with
+ regards to Type Inclusion
+ Constraints
+
+
+
+ Type Inclusion Constraints are applied
+ only to types defined in assemblies that also satisfy the
+ Assembly Inclusion Constraint
+
+ No matter whether any given Type satisfies
+ the Type Inclusion Contstraint, if the
+ Type is defined in an assembly that fails to
+ satisfy the Assembly Inclusion Constraint, the
+ Type will not be scanned for Object
+ Defintions.
+
+
+
+ There is always an implicit additional Type
+ Inclusion Constraint of "...and the
+ Type must have the [Configuration]
+ attribute applied to it"
+
+ No Type that does not have the [Configuration]
+ attribute applied to its declaration will ever be scanned regardless
+ of any Type Inclusion Constraint.
+
+
+
+
+
+
+ Advanced Scanning Behavior
+
+ In some cases, you may want more fine-grained control of the
+ scanning behavior the CodeConfigApplicationContext. In
+ this section, we explore the various techniques for achieving this level
+ of control.
+
+
+ Combining Root Path, Assembly Constraints, and Type
+ Constraints
+
+ The CodeConfigApplicationContext provides
+ several .ScanXXX(...) method overloads that accept
+ both an Assembly Constraint and a Type Constraint. These may be combined
+ as in the following example:
+
+ var ctx = new CodeConfigApplicationContext();
+ctx.Scan(assy => assy.FullName.Name.BeginsWith("Config"), type => type.Name.Contains("Infrastructure"));
+
+ Note that it is not possible to exclude specific types from the
+ scanning process using these overloads of the
+ .Scan(...) method. To get type-exclusion control, you
+ must instantiate and pass in your own instance of the
+ AssemblyObjectDefinitionScanner as described in the
+ following section(s).
+
+
+
+ Using your own AssemblyObjectDefintionScanner Instance
+
+ If you need more fine-grained control of the scanning behavior of
+ the CodeConfigApplicationContext, you can instantiate
+ and configure your own instance of the
+ AssemblyObjectDefinitionScanner and pass it to the
+ .Scan(...) method directly. The
+ AssemblyObjectDefinitonScanner provides many methods
+ for defining the contraints that will control the scanning
+ process.
+
+
+ Scanning Specific Assemblies and Types
+
+ The AssemblyObjectDefinitionScanner provides
+ methods that permit specific assemblies or types to be included or
+ excluded.
+
+ var scanner = new AssemblyObjectDefinitionScanner();
+
+scanner.AssemblyHavingType<MyConfigurations>(); //add the assembly containing this type to the list of assemblies to be scanned
+scanner.IncludeType<MySpecialConfiguration>(); //add this specific type the list of types to be scanned
+scanner.ExcludeType<MyConfigurationToBeIgnored>(); //exclude this specific type from the list of types to be scanned
+
+var ctx = new CodeConfigApplicationContext();
+ctx.Scan(scanner);
+
+ For those that prefer a more fluent feel to the
+ AssemblyObjectDefinitionScanner API, there are
+ methods that permit successive filter criteria to be strung together
+ in a sequence as in the following example:
+
+ var scanner = new AssemblyObjectDefinitionScanner();
+
+scanner
+ .WithAssemblyFilter(assy => assy.FullName.Name.StartsWith("Config"))
+ .WithIncludeFilter(type => type.Name.Contains("MyApplication"))
+ .WithExcludeFilter(type => type.Name.EndsWith("Service"))
+ .WithExcludeFilter(type => type.Name.StartsWith("Microsoft"));
+
+var ctx = new CodeConfigApplicationContext();
+ctx.Scan(scanner);
+
+
+
+
+ Use of XML Namespace and scanning
+ By default, classes attributed with [Component] , [Repository] , [Service] ,
+ [Controller] , [Configuration] or a custom attribute that extends [Component] are the only
+ detected candidate components. However, you can modify and extend this behavior simply by
+ applying custom filters. Add them as include-filter or
+ exclude-filter sub-elements of the component-scan
+ element. Each filter element requires the type and expression attributes. The following
+ table describes the filtering options.
+
+
+ Table Filter Types
+
+
+
+
+
+
+ Filter Type
+ Example Expression
+ Description
+
+
+
+
+ attribute
+ Spring.Stereotype.RepositoryAttribute, Spring.Core
+ An attribute to be present at the type level in target components.
+
+
+ assignable
+ My.Namespace.IFoo, My.Assembly
+ A class (or interface) that the target components are assignable to
+ (extend/implement).
+
+
+ regex
+ My.NameSpace.*.*Dao
+ A regex expression to be matched by the target components class names.
+
+
+
+ custom
+ My.Namespace.MyTypeFilter, My.Assembly
+ A custom implementation of the
+ Spring.Context.Attributes.TypeFilters.ITypeFilter interface.
+
+
+
+
+
+ The following example shows the XML configuration ignoring all [Repository] attributed
+ classes and only scanning types with names that end with Dao using "stub" repositories
+ instead.
+ <objects>
+
+ <context:component-scan base-assemblies="My.Namespace">
+ <context:include-filter type="regex" expression=".*Dao"/>
+ <context:exclude-filter type="annotation" expression="Spring.Stereotype.RepositoryAttribute, Spring.Core"/>
+ </context:component-scan>
+
+</beans>
+
+
diff --git a/doc/reference/src/codeconfig-migration-example.xml b/doc/reference/src/codeconfig-migration-example.xml
new file mode 100644
index 00000000..5d726095
--- /dev/null
+++ b/doc/reference/src/codeconfig-migration-example.xml
@@ -0,0 +1,700 @@
+
+
+ Introducing CodeConfig
+
+
+ A Dependency Injection Example
+
+ We will introduce the new code based approach by working with a very
+ simple application that will provide us the context to understand the
+ concepts of CodeConfig. We start by examining a sample application that
+ uses Spring.NET configured via ‘traditional’ XML configuration files. Then
+ we show how CodeConfig can be used to achieve the same results without any
+ XML configuration files at all.
+
+ To begin with, let’s explore the sample application that we will be
+ working with. This sample app is included in the Spring.NET CodeConfig
+ download package in the
+ /examples/Spring.CodeConfig.Migration folder.
+
+ To keep things simple, it’s just a .NET console application designed
+ to calculate and display the prime numbers between zero and an arbitrary
+ maximum number. There are four classes that must collaborate together to
+ do the work: ConsoleReporter,
+ PrimeGenerator,
+ PrimeEvaluationEngine, and
+ OutputFormatter. ConsoleReporter
+ depends on the PrimeGenerator which in turn depends on
+ the PrimeEvaluationEngine to calculate the prime
+ numbers. ConsoleReporter also depends on
+ OutputFormatter to format the results. The main console
+ application then simply asks ConsoleReporter to write
+ its report and ConsoleReporter goes to work. The
+ following Figure is a UML class diagram showing a simple way to visualize
+ the dependencies between these objects.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A simple Main() method that would do this without
+ the Spring.NET container could look something like Listing 1. Note the
+ in-line injection of dependencies via constructor arguments that builds up
+ the collaborating objects.
+
+ //Listing 1 (sample Main method not using Spring.NET)
+static void Main(string[] args)
+{
+ ConsoleReport report = new ConsoleReport(
+ new OutputFormatter(),
+ new PrimeGenerator(new PrimeEvaluationEngine()));
+
+ report.MaxNumber = 1000;
+ report.Write();
+
+ Console.WriteLine("--- hit enter to exit --");
+ Console.ReadLine();
+}
+
+ Using Spring.NET, as opposed to manually injecting dependencies as
+ in Listing 1, the collaborating objects are composed together with their
+ dependencies injected by the Spring.NET container at run-time. Initially,
+ the configuration of these objects is controlled from a Spring.NET XML
+ configuration file (see Listing 2).
+
+ <!-- Listing 2 (Spring.NET XML Configuration file, application-context.xml) -->
+<?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net">
+
+ <object name="ConsoleReport" type="Primes.ConsoleReport, Primes">
+ <constructor-arg ref="PrimeGenerator"/>
+ <constructor-arg ref="OutputFormatter"/>
+ <property name="MaxNumber" value="1000"/>
+ </object>
+
+ <object name="PrimeGenerator" type="Primes.PrimeGenerator, Primes">
+ <constructor-arg>
+ <object type="Primes.PrimeEvaluationEngine, Primes"/>
+ </constructor-arg>
+ </object>
+
+ <object name="OutputFormatter" type="Primes.OutputFormatter, Primes"/>
+
+</objects>
+
+ In Listing 2 you can also see the use of “ref”
+ element to refer to collaborating objects and the property
+ “MaxNumber” being set to “1000” on
+ the ConsoleReport object after it’s constructed. This
+ is the maximum number up to which we want the software to calculate prime
+ numbers. In Listing 3 we see the construction of the
+ XmlApplicationContext which is initialized by passing
+ it the name of the XML Configuration file. This container is then used to
+ resolve the ConsoleReport object with all of its
+ dependencies properly satisfied and its MaxNumber
+ property assigned the value of 1000.
+
+ //Listing 3 (initializing the XmlApplicationContext container)
+static void Main(string[] args)
+{
+ IApplicationContext ctx = CreateContainerUsingXML();
+
+ ConsoleReport report = ctx["ConsoleReport"] as ConsoleReport;
+ report.Write();
+
+ ctx.Dispose();
+
+ Console.WriteLine("--- hit enter to exit --");
+ Console.ReadLine();
+}
+
+private static IApplicationContext CreateContainerUsingXML()
+{
+ return new XmlApplicationContext("application-context.xml");
+}
+
+ While this XML-based configuration is well-understood by Spring.NET
+ users and others alike as a common method for expressing configuration
+ settings, it suffers from several challenges common to all XML file
+ including being overly-verbose and full of string-literals that are
+ unfriendly to most of the modern refactoring tools.
+
+
+
+ Migration to CodeConfig
+
+ To reduce or even eliminate the use of XML for configuring the
+ Spring.NET DI container, let’s look at how we can express the same
+ configuration metadata in code using Spring.NET CodeConfig. There are
+ several steps to using CodeConfig. We will look at each of them in the
+ likely sequence that one would follow to convert an existing XML-based
+ configuration for Spring.NET over to use the CodeConfig approach.
+
+
+ The CodeConfig Classes
+
+
+ Creating the CodeConfig Classes
+
+ First, we need to construct one or more classes to contain our
+ configuration metadata and attribute them properly. Spring.NET
+ CodeConfig relies upon attributes applied to classes and methods to
+ convey its metadata. Shown in Listing 4 is the CodeConfig class
+ (PrimesConfiguration) for our sample application.
+ // Listing 4, (Spring.NET Configuration Class, PrimesConfiguration.cs)
+using System;
+using System.Configuration;
+using Primes;
+using Spring.Context.Attributes;
+
+namespace SpringApp
+{
+ [Configuration]
+ public class PrimesConfiguration
+ {
+ [ObjectDef]
+ public virtual ConsoleReport ConsoleReport()
+ {
+ ConsoleReport report = new ConsoleReport(OutputFormatter(), PrimeGenerator());
+
+ report.MaxNumber = Convert.ToInt32(ConfigurationManager.AppSettings.Get("MaximumNumber"));
+ return report;
+ }
+
+ [ObjectDef]
+ public virtual IOutputFormatter OutputFormatter()
+ {
+ return new OutputFormatter();
+ }
+
+ [ObjectDef]
+ public virtual IPrimeGenerator PrimeGenerator()
+ {
+ return new PrimeGenerator(new PrimeEvaluationEngine());
+ }
+ }
+}
+
+
+
+ Elements of the CodeConfig Classes
+
+ Let’s explore the important elements of the CodeConfig file in
+ Listing 4 to understand how it can convey the same information to the
+ Spring.NET container as the XML file in Listing 2.
+
+
+ The Class
+
+ At the class level, you will notice the
+ PrimesConfiguration class has the[Configuration]
+ attribute applied to it. During the initialization phase of the DI
+ container, Spring.NET CodeConfig reads classes with these
+ attributes. Note that there is no specific inheritance hierarchy
+ required of a configuration class: no special base class or
+ interface implementation is required, leaving you free to leverage
+ inheritance and polymorphism to achieve some interesting
+ configuration and composition scenarios. Also note these special
+ identifying attributes are only applied to your CodeConfig classes,
+ not the types for which they are providing object definition
+ metadata. This means that your classes that do the work of your
+ application (e.g., ConsoleReport,
+ PrimeGenerator, etc.) are free to remain
+ undiluted POCO (Plain-Old-CLR-Object) classes that have themselves
+ no direct dependency on the Spring.NET framework.
+
+
+
+ The Methods
+
+ At the member level of the
+ PrimesConfiguration class, you will notice
+ several methods having the [ObjectDef]
+ attribute. This attribute identifies the method to which it is
+ applied as being the logical representation of a single object
+ definition for the Spring.NET container.
+
+ To begin understanding how this works let’s look at the
+ simplest of the definitions, that of the OutputFormatter. Let’s
+ start with the method visibility: all [ObjectDef]
+ methods must be declared both public and virtual.
+
+
+ Why must the [ObjectDef] methods be virtual?
+
+ The requirement for the [ObjectDef]
+ methods being virtual comes from the need when using CodeConfig
+ for the container to proxy [ObjectDef]
+ methods on the [Configuration]
+ classes. When the container is asked for an object, this proxy
+ intercepts the invocation of the [ObjectDef]
+ methods and ensures that requests for objects respect object
+ scoping rules like singleton and prototype. Singleton scope
+ ensures that if you ask the container multiple times for the same
+ named object, it will always return the same instance rather than
+ a new one each time. Singleton scope is common in server-side
+ programming and is the default lifecycle in Spring.NET.
+
+
+ The method return type, IOutputFormatter,
+ becomes the type that the DI container will be configured to
+ register. The method name itself,
+ OutputFormatter, is the equivalent of the id or
+ name that will be assigned to the object in the container. This name
+ can also be controlled by setting the Names
+ property on the [ObjectDef]
+ attribute itself.
+
+ The body of the OutputFormatter() method
+ simply creates a new instance of the
+ OutputFormatter and returns it. In simple terms,
+ we can think of the OutputFormatter() method as a
+ factory method that knows how to construct and return an instance of
+ something that implements the IOutputFormatter
+ interface (in this case, the concrete
+ OutputFormatter class).
+
+
+
+ More Complex Methods
+
+ To understand a slightly more complex [ObjectDef]
+ method, let’s now examine the PrimeGenerator()
+ method. Given what we already know about CodeConfig, it’s easy to
+ see that the PrimeGenerator() method describes an
+ Object Definition that will be registered with the container under
+ the name “PrimeGenerator” (the method name) and
+ the type IPrimeGenerator (the return type of the
+ method).
+
+ The method needs to return a new
+ PrimeGenerator but unlike the
+ OutputFormater class that offers an empty default
+ constructor, the PrimeGenerator class’ only
+ public constructor requires an instance of the
+ PrimeEvaluationEngine class be passed to it. To
+ satisfy this constructor dependency, we simply create a new
+ PrimeEvaluationEngine object in-line and pass it
+ to the new PrimeGenerator class. In this way, the
+ dependency between PrimeGenerator and
+ PrimeEvaluationEngine is satisfied in much the
+ same way as when coded ‘by hand’ as shown in Listing 1.
+
+ As a slightly more complex [ObjectDef]
+ example, let’s examine the ConsoleReport() method
+ next. This method needs to return a new
+ ConsoleReport instance, but as with the
+ PrimeGenerator class we lack a zero-argument
+ public constructor. The only public constructor of the
+ ConsoleReport class requires an
+ IOutputFormatter instance and an
+ IPrimeGenerator instance be provided. In our call
+ to new up an instance of the ConsoleReport class
+ in the ConsoleReport()[ObjectDef]
+ method, we are invoking the other [ObjectDef]
+ methods themselves to return these types. Since these other methods
+ in turn return IOutputFormatter and
+ IPrimeGenerator instances respectively, calls to
+ these other methods will satisfy the constructor dependency of the
+ ConsoleReport class and thus permit us to create
+ a new ConsoleReport to return at the end of the
+ ConsoleReport() method itself. In this manner, we
+ are delegating from one [ObjectDef] method to
+ the other [ObjectDef]
+ methods to create the object graph that we seek to return from the
+ call to the ConsoleReport() method.
+
+
+
+ Controlling Properties on Objects
+
+ But what about the “MaxNumber” property
+ that is set for the ConsoleReport object in the
+ XML file in Listing 2? As you can see from Listing 4, setting this
+ property on our ConsoleReport object is as simple
+ as…well, setting the property on our
+ ConsoleReport object! Since our
+ ConsoleReport() method merely has to return a new
+ ConsoleReport instance, we are completely free to
+ use any approach (in code) we choose to modify the
+ ConsoleReport instance before we return it. In
+ this case, it’s a simple matter of reading the value out of the
+ App.Config file and then setting the property to
+ the desired value before we return the instance of the
+ ConsoleReport object from the method.
+
+
+
+
+
+ Creating and Initializing the Application Context
+
+ Once we have translated the XML configuration file in Listing 2
+ into the CodeConfig class in Listing 4, we need to tell our application
+ to use it. For that, we need to switch from encapsulating our container
+ in the Spring.NET XmlApplicationContext to
+ encapsulating it in the CodeConfigApplicationContext
+ instead. Just as the XmlApplicationContext is
+ designed to use XML as the initial entry point to its configuration
+ settings, the CodeConfigApplicationContext is
+ designed to scan assemblies for [Configuration]
+ classes and [ObjectDef]
+ methods as the initial entry point to its configuration settings.
+ Listing 5 shows the CreateContainerUsingCodeConfig()
+ method from the Program.cs file in the sample
+ application that demonstrates this process.
+
+ //Listing 5 (bootstrapping the CodeConfigApplicationContext from Program.cs)
+private static IApplicationContext CreateContainerUsingCodeConfig()
+{
+ CodeConfigApplicationContext ctx = new CodeConfigApplicationContext();
+ ctx.ScanAllAssemblies();
+ ctx.Refresh();
+ return ctx;
+}
+
+ After instantiating the
+ CodeConfigApplicationContext, we next invoke the
+ ScanAllAssemblies() method to perform the scanning
+ for the [Configuration]-attributed
+ classes and [ObjectDef]-attributed
+ methods within our project. Lastly, the container is initialized by
+ calling the Refresh() method and then the
+ ready-to-use context is returned from the method. In the invocation of
+ the ScanAllAssemblies() method, we are asking the
+ CodeConfigApplicationContext to scan the current
+ AppDomain’s root folder and all subfolders recursively for all
+ assemblies that might contain CodeConfig classes (classes having the
+ [Configuration]
+ attribute).
+
+
+
+
+ More Granular Control Using CodeConfig
+
+ The example in Listing 4 and Listing 5 demonstrates only the most
+ basic use-cases for CodeConfig. More granular control over each of the
+ definitions is provided by applying additional attributes to the [Configuration]
+ classes and [ObjectDef]
+ methods and by setting various values on these attributes. Among these are
+ the following:
+
+
+
+ [Scope] for
+ controlling object lifecycle settings on a [ObjectDef]
+ such as singleton, prototype, etc.
+
+
+
+ [Import] for
+ chaining [Configuration]
+ classes together so that you can logically divide your [ObjectDef]
+ methods among multiple classes in much the same way you may do so with
+ multiple XML files that provide pointers to other XML files
+
+
+
+ [ImportResource]
+ for combining [Configuration]
+ classes with any of Spring.NET’s many implementations of its
+ IResource abstraction (file://, assembly://, etc.),
+ the most common one being an XML resource so that you can define part
+ of your configuration metadata in [Configuration]
+ classes and other parts of it in XML files as either embedded
+ resource(s) in your assemblies or as file(s) on disk.
+
+
+
+ [Lazy] for
+ controlling lazy instantiation of singleton objects
+
+
+
+ If you require aliases (additional, multiple names) for the Type
+ in the container, the [ObjectDef]
+ attribute also accepts an array of strings that if provided will be
+ registered as aliases for the Type registration.
+
+
+
+ In addition, finer-grained control of the specific assemblies to
+ scan, and specific [Configuration]
+ classes to include and/or exclude is supported by the scanning API. It is
+ also possible to compose configurations by dividing your [ObjectDef]
+ methods into multiple different [Configuration]
+ classes and then to assemble them as building blocks to configure your
+ container as it is initialized.
+
+ The CodeConfig approach enables us to express the same configuration
+ metadata to our Dependency Injection container as the XML file in Listing
+ 2 had provided, but in a form that is at once both significantly more
+ powerful and flexible as well as more resilient to the refactoring our
+ container-managed application objects.
+
+ To address additional common non-XML configuration scenarios, such
+ as the XML schemas for AOP and Transaction management, Spring.NET is also
+ evolving a more fluent-style configuration API that will build upon
+ CodeConfig in even more flexible ways in the near future including
+ convention-based registration of objects.
+
+
+
+ Organizing and Composing Multiple [Configuration] Classes
+
+ The examples referenced in this
+ document and provided in this distribution almost all employ merely a
+ single [Configuration] class
+ from which their ApplicationContext is to be configured. For these simple
+ examples this approach is viable but just as is the case when configuring
+ the ApplicationContext via XML, any significantly complex solution is
+ likely to require separating your [ObjectDef] methods into
+ multiple [Configuration]
+ classes.
+
+ Just as there are several strategies for effectively managing
+ multiple XML configuration files, so too are there many options available
+ to the developer to organize and compose multiple [Configuration] classes
+ together in a larger solution. This section doesn't attempt to cover all
+ of the available options in deep detail, but is intended to provide a
+ high-level understanding of some of the techniques that can be combined
+ together to help manage multiple such classes. Users familair with the
+ common techniques for composing together multiple XML configuration files
+ for Spring.NET will recognize some of these same patterns applied to [Configuration] classes
+ in the following sections as well.
+
+
+ Multiple Stand-Alone Configuration Classes
+
+ The simplest organization approach is providing multiple
+ stand-alone [Configuration]
+ classes. In this scenario, [ObjectDef] methods are
+ organized into separate [Configuration]
+ classes but each of the [Configuration]
+ classes is entirely self-contained and unrealted to the others. The
+ decomposition principles can of course be anything of your choosing. One
+ simple possibility might be to divide your configuration data between
+ different kinds of services as in the following example:
+
+ [Configuration]
+public class WcfServicesConfigurations
+{
+ [ObjectDef]
+ public virtual IWebService MySpecialService()
+ {
+ //construct and return a IWebService implementation here
+ }
+}
+
+[Configuration]
+public class RepositoryServicesConfigurations
+{
+ [ObjectDef]
+ public virtual ICustomerRepository MyCustomerRepository()
+ {
+ //construct and return a ICustomerRepository implementation here
+ }
+
+ [ObjectDef]
+ public virtual IShippingRepository MyShippingRepository()
+ {
+ //construct and return a IShippingRepository implementation here
+ }
+}
+
+ In this example, both of these [Configuration]
+ classes would need to be explicitly scanned and registered with the
+ CodeConfigApplicationContext
+ since they each are completely stand-alone and both are needed for the
+ proper configuration of the ApplicationContext. Since these two classes
+ in this example have no interdependencies between them, each class may
+ be placed into a different file or even assembly.
+
+
+
+ High-Level [Configuration] Classes that [Import] Others
+
+ Another strategy for composing multiple [Configuration]
+ classes together is to devise one or more 'high-level entry-point'
+ classes and leverage the [Import] attribute
+ so that the scanning of the high-level class automatically imports one
+ or more lower-level classes. The high-level classes may contain
+ [ObjectDef] methods of their own or merely hold reference to one or
+ more [Import] classes as needed.
+
+ [Configuration]
+[Import(typeof(MyWebServicesConfigurations))]
+[Import(typeof(MyMessagingServicesConfigurations))]
+[Import(typeof(MyPersistenceServicesConfigurations))]
+public class ServicesConfigurations
+{
+ //rest of class here as needed
+}
+
+ In this example, only the
+ ServicesConfigurations class needs to be scanned
+ because the [Import]
+ attributes point directly to the other classes to scan for
+ [Configuration]
+ and [ObjectDef]
+ metadata.
+
+
+
+ Referencing [ObjectDef]s from one [Configuration] Class in
+ Another
+
+ Once you decompose your [ObjectDef]
+ methods into separate classes, often you will find that you have a need
+ to reference the objects defined in one [Configuration]
+ class when coding the [ObjectDef]
+ methods in another [Configuration]
+ class. The architecture of Spring CodeConfig for .NET makes it simple to
+ address this need: you can simply ask the ApplicationContext to resolve
+ the needed Type.
+
+ To understand how this works, its first important to understand
+ that [Configuration]
+ classes are themselves registered as types in the ApplicationContext
+ in addition to the types defined in their [ObjectDef]
+ methods. Combining that knowledge with the special
+ IApplicationContextAware interface in Spring.NET
+ allows us to ask the ApplicationContext to inject
+ itself into our [Configuration]
+ classes. This ApplicationContext is then available to us to resolve
+ requests for needed types that may be defined elsewhere, whether in
+ other [Configuration]
+ classes or perhaps even other XML files.
+
+ Let's explore the following example where the
+ SecondConfiguration class needs access to the
+ TransactionManager that is defined in the
+ FirstConfiguration class in order to properly build
+ and configure a CustomerRepository instance:
+
+ [Configuration]
+public class FirstConfiguration
+{
+ [ObjectDef]
+ public virtual TransactionManager MySpecialTransactionManager()
+ {
+ return new TransactionManager();
+ }
+}
+
+[Configuration]
+public class SecondConfiguration : IApplicationContextAware //note the interface implementation
+{
+ //field to hold the injected context
+ private IApplicationContext _context;
+
+ //property setter defined by the IApplcationContextAware interface
+ // so that the context can inject itself into the class
+ public IApplicationContext ApplicationContext { set { _context = value; } }
+
+ [ObjectDef]
+ public virtual ICustomerRepository CustomerRepository()
+ {
+ //to construct the CustomerRepository, we need a TransactionManager instance
+ // as a constructor argument so let's ask the injected context to resolve one for us
+ return new CustomerRepository(_context.GetObject<TransactionManager>());
+ }
+}
+
+//somewhere else in your solution the CustomerRepository class is defined as follows...
+public class CustomerRespository : ICustomerRespository
+{
+ private TransactionManager _transactionManager;
+
+ public CustomerRespository(TransactionManager transactionManager)
+ {
+ _transactionManager = transactionManager;
+ }
+}
+
+ In this way, there is no direct coupling between [Configuration]
+ classes and the SecondConfiguration class is only aware of the
+ ApplicationContext itself and the actual Types it needs to construct the
+ Types described in its [ObjectDef]
+ methods.
+
+
+
diff --git a/doc/reference/src/codeconfig-sample-apps.xml b/doc/reference/src/codeconfig-sample-apps.xml
new file mode 100644
index 00000000..c0703b95
--- /dev/null
+++ b/doc/reference/src/codeconfig-sample-apps.xml
@@ -0,0 +1,266 @@
+
+
+ Sample Applications
+
+
+ Overview
+
+ The Spring CodeConfig for .NET project includes three sample
+ applications:
+
+
+
+ Spring.IoCQuickStart.MovieFinder
+
+
+
+ Spring.MvcQuickStart
+
+
+
+ Spring.CodeConfig.Migration
+
+
+
+
+
+ Spring.IoCQuickStart.MovieFinder
+
+ The Spring.IoCQuickStart.MovieFinder sample application is the same
+ fundamental code as provided in the sample app by the same name that is
+ provided with the main Spring.NET
+ Framework download package. This section assumes you are already
+ familiar with the sample application as provided in that download package.
+ This version of this sample application has been modified to rely upon
+ CodeConfig for its Object Definitions.
+
+
+ Modifying App.config
+
+ The first modification to the existing sample application involves
+ changes to the <spring> element in the
+ App.config file:
+
+ <spring>
+
+ <parsers>
+ <!-- Equivalent to 'NamespaceParserRegistry.RegisterParser(typeof(ContextNamespaceParser));' -->
+ <parser type="Spring.Context.Config.ContextNamespaceParser, Spring.Core.Configuration" />
+ </parsers>
+
+ <context>
+ <!-- using embedded assembly configuration file -->
+ <resource uri="assembly://Spring.IocQuickStart.MovieFinder/Spring.IocQuickStart.MovieFinder/CodeConfigBootstrap.xml"/>
+ </context>
+
+ </spring>
+
+ The important changes here are the introducton of the
+ <parsers> section (to register the
+ ContextNamespaceParser required for CodeConfig) and
+ the change of the <resource> element to point
+ to the CodeConfigBootstrap.xml file instead of the
+ Appcontext.xml file as before.
+
+
+
+ Replacing Appcontext.xml with CodeConfigBootstrap.xml
+
+ Where before the Appcontext.xml contained all
+ of the XML-based object definitions for the application, in this case
+ the CodeConfigBootstrap.xml merely contains the
+ single instruction telling the context to use CodeConfig:
+
+ <?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:context="http://www.springframework.net/context">
+
+ <description>An example that demonstrates code based configuration for object definitions.</description>
+
+ <context:code-config/>
+
+</objects>
+
+
+ In this case, the single
+ <context:code-config/> element is sufficient to
+ tell the context to perform scanning for its object definition
+ metadata.
+
+
+
+ Introducing the MovieFinderConfiguration CodeConfig class
+
+ The final modification needed to migrate the sample application to
+ rely upon CodeConfig is to author the classes that will provide the
+ Object Definitions for the Application Context to discover when
+ performing the scan. In the case of this simple application, this is
+ encapsulated in the single new
+ MovieFinderConfiguration class as shown in the
+ following:
+
+ [Configuration]
+ public class MovieFinderConfiguration
+ {
+
+ [ObjectDef]
+ public virtual MovieLister MyMovieLister()
+ {
+ MovieLister movieLister = new MovieLister();
+ movieLister.MovieFinder = FileBasedMovieFinder();
+ return movieLister;
+
+ }
+
+ [ObjectDef]
+ public virtual IMovieFinder FileBasedMovieFinder()
+ {
+ return new ColonDelimitedMovieFinder(new FileInfo("movies.txt"));
+ }
+ }
+
+ Using a combination of [Configuration]
+ and [ObjectDef]
+ attributes, this class faithfully reproduces the same Object Definition
+ configuration as had been described by the
+ Appcontext.xml file in the iniitial sample
+ application as delivered with the main Spring.NET Framework
+ download.
+
+
+
+
+ Spring.MvcQuickStart
+
+ The Spring.MvcQuickStart sample application is the same fundamental
+ code as provided in the sample app by the same name that is provided with
+ the main
+ Spring.NET Framework download package. This section assumes you are
+ already familiar with the sample application as provided in that download
+ package. This version of this sample application has been modified to rely
+ upon CodeConfig for its Object Definitions.
+
+
+ Modifying Web.config
+
+ The first modification to the existing sample application involves
+ changes to the <spring> element in the
+ Web.config file:
+
+ <spring>
+ <parsers>
+ <!-- Equivalent to 'NamespaceParserRegistry.RegisterParser(typeof(ContextNamespaceParser));' -->
+ <parser type="Spring.Context.Config.ContextNamespaceParser, Spring.Core.Configuration" />
+ </parsers>
+
+ <context>
+ <resource uri="~/Config/CodeConfigBootsrap.xml"/>
+ </context>
+ </spring>
+
+ The important changes here are the introducton of
+ the<parsers> section (to register the
+ ContextNamespaceParser required for CodeConfig) and
+ the change of the <resource> element to point
+ to the CodeConfigBootstrap.xml file instead of the
+ controllers.xml file as before.
+
+ In addition, the section name for the
+ <parsers> element must be registered with the
+ <spring> sectionGroup as shown here so that the
+ element can be properly interpreted:
+
+ <configSections>
+ <sectionGroup name="spring">
+ <section name="context" type="Spring.Context.Support.MvcContextHandler, Spring.Web.Mvc"/>
+ <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
+ </sectionGroup>
+
+ <!--
+ remainder of configSections element here...
+ -->
+
+ </configSections>
+
+
+
+ Replacing controllers.xml with CodeConfigBootstrap.xml
+
+ Where before the controllers.xml file contained
+ all of the XML-based object definitions for the controllers for our MVC
+ application, in this case the CodeConfigBootstrap.xml
+ merely contains the single instruction telling the context to use
+ CodeConfig:
+
+ <?xml version="1.0" encoding="utf-8" ?>
+<objects xmlns="http://www.springframework.net"
+ xmlns:context="http://www.springframework.net/context">
+
+ <context:code-config/>
+
+</objects>
+
+ In this case, the single
+ <context:code-config/> element is sufficient to
+ tell the context to perform scanning for its object definition
+ metadata.
+
+
+
+ Introducing the ControllerConfiguration CodeConfig class
+
+ The final modification needed to migrate the sample application to
+ rely upon CodeConfig is to author the classes that will provide the
+ Object Definitions for the Application Context to discover when
+ performing the scan. In the case of this simple application, this is
+ encapsulated in the single new
+ ControllerConfiguration class as shown in the
+ following:
+
+ [Configuration]
+ public class ControllerConfiguration
+ {
+ [ObjectDef]
+ [Scope(ObjectScope.Prototype)]
+ public virtual HomeController HomeController()
+ {
+ HomeController controller = new HomeController();
+ controller.Message = "Welcome to ASP.NET MVC powered by Spring.NET (Code-Config)!";
+ return controller;
+ }
+ }
+
+ Using a combination of [Configuration]
+ and [ObjectDef]
+ attributes, this class faithfully reproduces the same Object Definition
+ configuration as had been described by the
+ controllers.xml file in the iniitial sample
+ application as delivered with the main Spring.NET Framework
+ download.
+
+
+
+
+ Spring.CodeConfig.Migration
+
+ This sample demonstates a step-by-step detailed examination of the
+ process of migrating an XML-configuration based solution to use CodeConfig
+ exclusively and is described in detail in the Introduction section of the
+ reference documents.
+
+
diff --git a/doc/reference/src/images/Migration_App_UML_Diagram.png b/doc/reference/src/images/Migration_App_UML_Diagram.png
new file mode 100644
index 00000000..501f8830
Binary files /dev/null and b/doc/reference/src/images/Migration_App_UML_Diagram.png differ
diff --git a/doc/reference/src/images/ScreenShot023.png b/doc/reference/src/images/ScreenShot023.png
new file mode 100644
index 00000000..41c76525
Binary files /dev/null and b/doc/reference/src/images/ScreenShot023.png differ
diff --git a/doc/reference/src/index.xml b/doc/reference/src/index.xml
index 78a9b353..2ffd0ce3 100644
--- a/doc/reference/src/index.xml
+++ b/doc/reference/src/index.xml
@@ -1,478 +1,645 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-]>
-
-
- The Spring.NET Framework
- Reference Documentation
- Version 1.3.2
- Last Updated August 1, 2011 (Latest documentation)
-
-
- Mark
- Pollack
-
-
- Rick
- Evans
-
-
- Aleksandar
- Seovic
-
-
- Bruno
- Baia
-
-
- Erich
- Eichinger
-
-
- Federico
- Spinazzi
-
-
- Rob
- Harrop
-
-
- Griffin
- Caprio
-
-
- Ruben
- Bartelink
-
-
- Choy
- Rim
-
-
- Erez
- Mazor
-
-
- Stephen
- Bohlen
-
-
- The Spring
- Java Team
-
-
-
-
- Copies of this document may be made for your own use and for
- distribution to others, provided that you do not charge any fee for such
- copies and further provided that each copy contains this Copyright
- Notice, whether distributed in print or electronically.
-
-
-
-
- &preface;
- &overview;
- &background;
- &migration;
-
- Core Technologies
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+
+ The Spring.NET Framework
+
+ Reference Documentation
+
+ Version 2.0.0
+
+ Last Updated January 11, 2013 (Latest
+ documentation)
+
+
+
+ Mark
+
+ Pollack
+
+
+
+ Rick
+
+ Evans
+
+
+
+ Aleksandar
+
+ Seovic
+
+
+
+ Bruno
+
+ Baia
+
+
+
+ Erich
+
+ Eichinger
+
+
+
+ Federico
+
+ Spinazzi
+
+
+
+ Rob
+
+ Harrop
+
+
+
+ Griffin
+
+ Caprio
+
+
+
+ Ruben
+
+ Bartelink
+
+
+
+ Choy
+
+ Rim
+
+
+
+ Erez
+
+ Mazor
+
+
+
+ Stephen
+
+ Bohlen
+
+
+
+ The Spring
+
+ Java Team
+
+
+
+
+ Copies of this document may be made for your own use and for
+ distribution to others, provided that you do not charge any fee for such
+ copies and further provided that each copy contains this Copyright
+ Notice, whether distributed in print or electronically.
+
+
+
+
+
+ &preface;
+
+ &overview;
+
+ &background;
+
+ &migration;
+
+
+ Core Technologies
+
+
+ This initial part of the reference documentation covers all of
+ those technologies that are absolutely integral to the Spring
+ Framework.
+
+ Foremost amongst these is the Spring Framework's Inversion of
+ Control (IoC) container. A thorough treatment of the Spring Framework's
+ IoC container is closely followed by comprehensive coverage of Spring's
+ Aspect-Oriented Programming (AOP) technologies. The Spring Framework has
+ its own AOP framework, which is conceptually easy to understand, and
+ which successfully addresses the 80% sweet spot of AOP requirements in
+ enterprise programming.
+
+ The core functionality also includes an expression language for
+ lightweight scripting and a ui-agnostic validation framework.
+
+ Finally, the adoption of the test-driven-development (TDD)
+ approach to software development is certainly advocated by the Spring
+ team, and so coverage of Spring's support for integration testing is
+ covered (alongside best practices for unit testing). The Spring team
+ have found that the correct use of IoC certainly does make both unit and
+ integration testing easier (in that the presence of properties and
+ appropriate constructors on classes makes them easier to wire together
+ on a test without having to set up service locator registries and
+ suchlike)... the chapter dedicated solely to testing will hopefully
+ convince you of this as well.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &objects;
+
+ &objects-misc;
+
+ &resources;
+
+ &threading;
+
+ &pool;
+
+ &misc;
+
+ &expressions;
+
+ &validation;
+
+
+
+ &aop;
+
+ &aop-aspect-library;
+
+ &logging;
+
+ &testing;
+
+
+
+ Middle Tier Data Access
+
+
+ This part of the reference documentation is concerned with othe
+ middle tier, and specifically the data access responsibilities of said
+ tier.
+
+ Spring's comprehensive transaction management support is covered
+ in some detail, followed by thorough coverage of the various middle tier
+ data access frameworks and technologies that the Spring Framework
+ integrates with.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &transaction;
+
+ &dao;
+
+ &dbprovider;
+
+ &ado;
+
+ &orm;
+
+
+
+ The Web
+
+
+ This part of the reference documentation covers the Spring
+ Framework's support for the presentation tier, specifically web-based
+ presentation tiers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &web;
+
+ &ajax;
+
+ &web-mvc;
+
+ &web-mvc3;
+
+
+
+ Services
+
+
+ This part of the reference documentation covers the Spring
+ Framework's integration with .NET distributed technologies such as .NET
+ Remoting, Enterprise Services, Web Services. Integration with WCF
+ Services is forthcoming. Please refer to the introduction chapter for
+ more details.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &psa-intro;
+
+ &remoting;
+
+ &services;
+
+ &webservices;
+
+ &wcf;
+
+
+
+ Integration
+
+
+ This part of the reference documentation covers the Spring
+ Framework's integration with a number of related enterprise .NET
+ technologies.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &messaging;
+
+ &messaging-ems;
+
+ &msmq;
+
+ &scheduling;
+
+ &templating;
+
+
+
+ Code-Based Configuration
-
- This initial part of the reference documentation covers
- all of those technologies that are absolutely integral
- to the Spring Framework.
-
-
- Foremost amongst these is the Spring Framework's
- Inversion of Control (IoC) container. A thorough treatment
- of the Spring Framework's IoC container is closely followed
- by comprehensive coverage of Spring's Aspect-Oriented
- Programming (AOP) technologies. The Spring Framework has
- its own AOP framework, which is conceptually easy to understand,
- and which successfully addresses the 80% sweet spot of AOP
- requirements in enterprise programming.
-
-
- The core functionality also includes an expression language
- for lightweight scripting and a ui-agnostic validation framework.
-
-
- Finally, the adoption of the test-driven-development (TDD)
- approach to software development is certainly advocated by
- the Spring team, and so coverage of Spring's support for
- integration testing is covered (alongside best practices for
- unit testing). The Spring team have found that the correct
- use of IoC certainly does make both unit and integration
- testing easier (in that the presence of properties and
- appropriate constructors on classes makes them
- easier to wire together on a test without having to set up
- service locator registries and suchlike)... the chapter
- dedicated solely to testing will hopefully convince you of
- this as well.
-
+ In this reference document, we’ll explore the newest addition to
+ the configuration story for the Spring.NET Dependency Injection
+ container: code-based configuration, or simply CodeConfig, intended to
+ begin to address many of the shortcomings of the XML-based configuration
+ approach.
+
+ At the core of Spring.NET is a powerful and flexible dependency
+ injection container, offering object assembly and construction services
+ atop which the remainder of the Spring.NET Framework is based.
+ Historically, the primary manner of configuring this dependency
+ injection container has been XML configuration files. Object
+ definitions, essentially recipes to be used by the container when
+ constructing objects of various types, are expressed in XML and then
+ parsed and interpreted by the container as it is initialized at
+ run-time.
+
+ While there are several positive aspects to expressing
+ configuration metadata in XML files, there are also many problems with
+ this approach including the verbosity of XML and its heavy dependence on
+ string-literals which are both prone to typing errors and unusually
+ resistant to most modern refactoring tools in use today. The CodeConfig
+ approach removes these problems by providing a type safe, code-based,
+ approach to dependency injection. It keeps the configuration metadatda
+ external to your class so your class can be a POCO, free of any DI
+ related annotations.
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
- &objects;
- &objects-misc;
- &resources;
- &threading;
- &pool;
- &misc;
- &expressions;
- &validation;
-
- &aop;
- &aop-aspect-library;
- &logging;
- &testing;
-
-
- Middle Tier Data Access
-
-
- This part of the reference documentation is concerned
- with othe middle tier, and specifically the data access
- responsibilities of said tier.
-
-
- Spring's comprehensive transaction management support is
- covered in some detail, followed by thorough coverage of
- the various middle tier data access frameworks and
- technologies that the Spring Framework integrates with.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- &transaction;
- &dao;
- &dbprovider;
- &ado;
- &orm;
-
-
- The Web
-
-
- This part of the reference documentation covers the
- Spring Framework's support for the presentation tier,
- specifically web-based presentation tiers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- &web;
- &ajax;
- &web-mvc;
- &web-mvc3;
-
-
- Services
-
-
- This part of the reference documentation covers
- the Spring Framework's integration with .NET distributed
- technologies such as .NET Remoting, Enterprise Services,
- Web Services. Integration with WCF Services is forthcoming.
- Please refer to the introduction chapter for more details.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- &psa-intro;
- &remoting;
- &services;
- &webservices;
- &wcf;
-
-
- Integration
-
-
- This part of the reference documentation covers
- the Spring Framework's integration with a number of
- related enterprise .NET technologies.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- &messaging;
- &messaging-ems;
- &msmq;
- &scheduling;
- &templating;
-
-
- VS.NET Integration
-
-
- This part of the reference documentation covers
- the Spring Framework's integration with VS.NET
-
-
-
-
-
-
-
- &vsnet;
-
-
- Quickstart applications
-
-
- This part of the reference documentation covers
- the quickstart applications included with
- Spring that demonstrate features in a code centric
- manner.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- &quickstarts;
- &aop-quickstart;
- &remoting-quickstart;
- &web-quickstart;
- &springair;
- &data-quickstart;
- &tx-quickstart;
- &nh-quickstart;
- &quartz-quickstart;
- &nms-quickstart;
- &ems-quickstart;
- &msmq-quickstart;
- &wcf-quickstart;
-
-
- Spring.NET for Java developers
-
-
- This part of the reference documentation
- is for Java developers who would like a quick
- orientation to what is different between
- the Java and .NET versions of the framework.
-
-
-
-
-
-
-
- &javadevelopers;
-
-
-
-
- Appendices
- &classic-spring;
- &xsd-configuration;
- &xml-custom;
- &xsd;
-
-
-
+
+
+ &codeconfig-migration-example;
+ &codeconfig-context;
+ &codeconfig-attribute-reference;
+ &codeconfig-sample-apps;
+
+
+
+ VS.NET Integration
+
+
+ This part of the reference documentation covers the Spring
+ Framework's integration with VS.NET
+
+
+
+
+
+
+
+
+ &vsnet;
+
+
+
+ Quickstart applications
+
+
+ This part of the reference documentation covers the quickstart
+ applications included with Spring that demonstrate features in a code
+ centric manner.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &quickstarts;
+
+ &aop-quickstart;
+
+ &remoting-quickstart;
+
+ &web-quickstart;
+
+ &springair;
+
+ &data-quickstart;
+
+ &tx-quickstart;
+
+ &nh-quickstart;
+
+ &quartz-quickstart;
+
+ &nms-quickstart;
+
+ &ems-quickstart;
+
+ &msmq-quickstart;
+
+ &wcf-quickstart;
+
+
+
+ Spring.NET for Java developers
+
+
+ This part of the reference documentation is for Java developers
+ who would like a quick orientation to what is different between the Java
+ and .NET versions of the framework.
+
+
+
+
+
+
+
+
+ &javadevelopers;
+
+
+
+
+
+ Appendices
+
+ &classic-spring;
+
+ &xsd-configuration;
+
+ &xml-custom;
+
+ &xsd;
+
+
diff --git a/doc/reference/src/objects.xml b/doc/reference/src/objects.xml
index c135e961..e258ceef 100644
--- a/doc/reference/src/objects.xml
+++ b/doc/reference/src/objects.xml
@@ -6392,17 +6392,8 @@ ctx.Refresh();
RootObjectDefinition, etc. Note a web version of this application class
has not yet been implemented.
- An example, with a yet to be created DLL
- scanner, that would get configuration metadata from the .dll named
- MyAssembly.dll located in the runtime path, would look something like
- this
-
- GenericApplicationContext ctx = new GenericApplicationContext();
-ObjectDefinitionScanner scanner = new ObjectDefinitionScanner(ctx);
-scanner.scan("MyAssembly.dll");
-ctx.refresh();
-
- Refer to the Spring API documentation for more information.
+ For a an even richer XML-free configuration experience, refer
+ instead to the Spring CodeConfig approach.