This blog post describes how you can access the configuration factory built into the Sitecore ASP.NET CMS to fulfill dependency injection using the web.config file. For more information about dependency injection, see my blog post Dependency Injection with the Sitecore ASP.NET CMS.
The configuration factory allows you to configure types and parameters passed at instantiation in the web.config file rather than using code. Specifying parameters inline can avoid the need for additional settings, configuration settings, and configuration files.
The configuration factory instantiates types through the Sitecore.Configuration.Factory static class. The configuration factory provides a form of dependency injection, adding processing before and after object instantiation, before object access. You can override and add values to configuration files and items in the databases to specify the types to implement specific features and the parameters to pass to those types.
The web.config file contains <sc:include> elements to explicitly include child configuration files. Configuration automatically includes any .config files in the /App_Config/Include subdirectory. In general, the term web.config indicates the effective Sitecore configuration after including files rather than the actual contents of web.config. You can access the /sitecore/admin/showconfig.aspx page to see the effective Sitecore configuration after applying include files.
This example that you can download consists of a configuration file for the /App_Config/Include subdirectory, the .NET class specified in that configuration file for the factory to instantiate, an interface for that class to implement (optional - you can use an abstract class or a concrete class instead of an interface), and a web control to exercise that interface. The type instantiated by the factory supports several types of configuration properties and features.
The remainder of this post describes the sample web.config include file, which defines the /configuration/sitecore/exampleSection/exampleType configuration element. The type attribute of this element specifies the type, including the assembly name. The web control invokes the Sitecore.Configuration.Factory.GetConfigNode() method to select this type definition element in the configuration file, and then invokes the Sitecore.Configuration.Factory.CreateObject<T>() method to instantiate that type.
<exampleType type="Sitecore.Sharedsource.Data.Example, assembly">
Elements nested within this configuration element correspond to constructor parameters, properties, and methods for the specified type.
Any <param> elements within a type definition element specify ordered parameters to the constructor. When possible, use properties rather than constructor parameters.
<param hint="1">First Constructor Argument</param>
<param hint="2">Second Constructor Argument</param>
By default, named elements in a type definition element correspond to properties of the type specified by the type attribute in the type definition element. Name these elements after the properties of your class and the factory will automatically set the corresponding properties to the enclosed value.
<stringProperty>String Property value</stringProperty>
You can use the hint attribute in a property definition element to indicate list types, such as the <publicList> element in the example. The names of the elements within the list definition element should be unique locally.
<arbitrary hint="1">First entry in public list</arbitrary>
<arbitrary hint="2">Second entry in public list</arbitrary>
Note that the names of the enclosed elements are arbitrary, but in web.config include files, at least in some versions of Sitecore, these elements should have unique names or unique attribute values as show in the example (not including an attribute named “key”). The same applies to the <param> elements used as constructor parameters.
You can use the hint attribute in a property definition element to instruct the factory to pass the values in the enclosed elements to a method, such as the <protectedList> element in the example. The example calls the AddToProtectedList() method on the instantiated object once for each enclosed element.
<arbitrary hint="1">First entry in protected list</arbitrary>
<arbitrary hint="2">Second entry in protected list</arbitrary>
I would generally use the protected list approach except when reusing an existing class that requires constructor parameters or already exposes the required list.
You can use method definition elements that use the hint attribute with the raw: prefix to invoke a specific method, such as the <arbitraryMethod> element in the example. For each element within the method definition element, the configuration factory invokes the method, passing a System.Xml.XmlNode representing the element in the web.config file. You could use this approach to pass a large volume or complex configuration information. This example calls the ArbitraryMethod() method twice:
<nested>First nested value in first container element</nested>
<second>Second nested value in first container element</second>
<arbitrary hint="2">First nested value in second container element</arbitrary>
The configuration factory has more complex features, such as using web.config variables in parameters and properties. You can see a lot of this in the /configuration/sitecore/databases/database elements in the default web.config file.
This configuration generated the following output, which seems to indicate that Sitecore sets properties and invokes methods in the order specified in the configuration:
5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : First constructor argument: First Constructor Argument5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : Second constructor argument: Second Constructor Argument5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : StringProperty set to String Property value5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : IntProperty set to 1015492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : PublicList accessed.5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : PublicList accessed.5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : First entry in protected list added to protected list.5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : Second entry in protected list added to protected list.5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : ArbitraryMethod invoked with <arbitrary hint="1"><nested>First nested value in first container element</nested><second>Second nested value in first container element</second></arbitrary>5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : ArbitraryMethod invoked with <arbitrary hint="2">First nested value in second container element</arbitrary>5492 14:52:40 INFO Sitecore.Sharedsource.Data.Example : ArbitraryMethod invoked with <hard-coded>Value hard-coded in Sitecore.Sharedsource.Web.UI.WebControls.ExampleTester</hard-coded>
For information about using web.config include files for configuration, see my blog post All About web config Include Files with the Sitecore ASP.NET CMS.
This is really awesome. I wasn't aware this applied to all custom classes configured in the Sitecore config. I did this before with an agent but this flexibility is great for agents, tasks, pipelines, events, etc. This is a must read guide for anyone that needs to customize Sitecore to run custom code within the client.
sdn.sitecore.net/.../include file patching facilities.aspx
Hey John, I wrote a post on Constructor Injection via the Sitecore Configuration Factory: sitecorejunkie.com/.../ Mike
john, in the config can i add custom attributes that can be set on the concrete class? For example: <exampleType customAttr="value" type="Sitecore.Sharedsource.Data.Example, assembly"> and sets the CustomAttr property on the Example class?