From: <jer...@us...> - 2009-01-02 23:58:21
|
Revision: 213 http://structuremap.svn.sourceforge.net/structuremap/?rev=213&view=rev Author: jeremydmiller Date: 2009-01-02 23:58:17 +0000 (Fri, 02 Jan 2009) Log Message: ----------- documentation Modified Paths: -------------- trunk/Source/HTML/AttributeNormalized.htm trunk/Source/HTML/ConfiguringStructureMap.htm trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/HTML/Default.htm trunk/Source/HTML/Diagnostics.htm trunk/Source/HTML/ExtendingStructureMap.htm trunk/Source/HTML/Generics.htm trunk/Source/HTML/Glossary.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/InstanceExpression.htm trunk/Source/HTML/Interception.htm trunk/Source/HTML/QuickStart.htm trunk/Source/HTML/RegistryDSL.htm trunk/Source/HTML/RetrievingServices.htm trunk/Source/HTML/ScanningAssemblies.htm Added Paths: ----------- trunk/Source/HTML/AutoMocker.htm trunk/Source/HTML/AutoWiring.htm trunk/Source/HTML/ChangingConfigurationAtRuntime.htm trunk/Source/HTML/Concepts.htm trunk/Source/HTML/FeatureList.htm trunk/Source/HTML/HowDoesStructureMapWork.htm trunk/Source/HTML/Menu.htm trunk/Source/HTML/ModularConfiguration.htm trunk/Source/HTML/Profiles.htm trunk/Source/HTML/Scoping.htm trunk/Source/HTML/SmartInstance.htm trunk/Source/HTML/UsingAttributes.htm trunk/Source/HTML/UsingSessionContext.htm trunk/Source/HTML/UsingTheContainerOutsideOfObjectFactory.htm trunk/Source/HTML/XmlReference.htm trunk/Source/HTML/jquery-1.2.6.js trunk/Source/HTML/structuremap.js trunk/Source/HTML/style.css Removed Paths: ------------- trunk/Source/HTML/ExplicitArguments.htm trunk/Source/HTML/InjectingServicesAtRuntime.htm Modified: trunk/Source/HTML/AttributeNormalized.htm =================================================================== --- trunk/Source/HTML/AttributeNormalized.htm 2008-12-22 14:57:59 UTC (rev 212) +++ trunk/Source/HTML/AttributeNormalized.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -1,25 +1,18 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title>Title</title> - <link rel="stylesheet" type="text/css" href="style.css"> - <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"> - <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> - <style type="text/css"> - .style1 - { - font-weight: bold; - } - </style> + <title>Attribute Normalized Instances</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> - <body> - <h1>Attribute Normalized Xml Instances</h1> + <body class="code"> <p>This style is a more terse configuration format that was added in version 1.0. My recommendaton is to always use attribute normalized Xml configuration by marking the <StructureMap> node with the MementoStyle="Attribute" attribute by default anytime you are using Xml configuration. </p> - <h4>Instance Root Node</h4> + <h2>Instance Root Node</h2> <p>An Instance is defined in Xml starting from a root node. The actual name of the root node varies depending upon the context that an Instance is being configured. For example, the AddInstance, DefaultInstance, @@ -31,7 +24,8 @@ <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red163\green21\blue21;\red0\green0\blue255;}??\fs20 [\cf3 Pluggable\cf0 (\cf4 "Color"\cf0 )]\par ?? \cf5 public\cf0 \cf5 class\cf0 \cf3 ColorRule\cf0 : \cf3 Rule\par ??\cf0 \{\par ?? \cf5 private\cf0 \cf5 string\cf0 _Color;\par ?? \cf5 public\cf0 \cf5 string\cf0 ID = \cf3 Guid\cf0 .NewGuid().ToString();\par ??\par ?? \cf5 public\cf0 ColorRule(\cf5 string\cf0 Color)\par ?? \{\par ?? _Color = Color;\par ?? \}\par ??\par ??\par ?? \cf5 public\cf0 \cf5 string\cf0 Color\par ?? \{\par ?? \cf5 get\cf0 \{ \cf5 return\cf0 _Color; \}\par ?? \}\par ?? \}} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> + <div class="code-sample" + style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> <p style="margin: 0px;"> [<span style="color: #2b91af;">Pluggable</span>(<span style="color: #a31515;">"Color"</span>)]</p> @@ -82,7 +76,7 @@ {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 <\cf3 Instance\cf1 \cf4 Key\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 \cf4 Type\cf1 =\cf0 "\cf1 Color\cf0 "\cf1 \cf4 Color\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 />} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> - <p style="margin: 0px;"> + <p style="margin: 0px;" class="code-sample"> <span style="color: blue;"> <</span><span style="color: #a31515;">Instance</span><span style="color: blue;"> </span> <span style="color: red;">Key</span><span style="color: blue;">=</span>"<span @@ -102,7 +96,7 @@ {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 <\cf3 Instance\cf1 \cf4 Key\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Widget.Color, StructureMap.Testing.Widget\cf0 "\cf1 \cf4 Color\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 />} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> - <p style="margin: 0px;"> + <p style="margin: 0px;" class="code-sample"> <span style="color: blue;"> <</span><span style="color: #a31515;">Instance</span><span style="color: blue;"> </span> <span style="color: red;">Key</span><span style="color: blue;">=</span>"<span @@ -114,26 +108,30 @@ style="color: blue;">Red</span>"<span style="color: blue;"> /></span></p> </div> <!--EndFragment--> -<p> </p> - <h4>Primitive Properties (Strings and basic value types)</h4> - <p>Primitive constructor or setter arguments are defined by - adding an attribute @propertyName="propertyValue" to the - instance node.="font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt;"> -<pre style="margin: 0px;"> [Pluggable("Color", "Only for testing")]</pre> -<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> ColorWidget : IWidget</pre> +<hr /> + <h2>Primitive Properties (Strings and basic value types)</h2> + <p>Primitive constructor or setter arguments are defined by adding an attribute + @propertyName="propertyValue" to the instance node. A class with + a string argument to the constructor,</p> +<div class="code-sample> + <pre style="margin: 0px;"> [Pluggable("Color", "Only for testing")]<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> ColorWidget : IWidget</pre> <pre style="margin: 0px;"> {</pre> <pre style="margin: 0px;"> <span style="color: blue;">public</span> ColorWidget(<span style="color: blue;">string</span> Color)</pre> <pre style="margin: 0px;"> {</pre> <pre style="margin: 0px;"> _Color = Color;</pre> <pre style="margin: 0px;"> }</pre> <pre style="margin: 0px;"> }</pre> + <pre style="margin: 0px;"> </pre> + <p style="margin: 0px;">would be configured like this in the Xml:</p> + </div> <br> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt;"> -<pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">Widget</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Color"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Red"</span><span style="color: fuchsia;"> </span><span style="color: #FF0000">Color</span><span style="color: blue;">="Red" /></span></pre> +<pre style="margin: 0px;" class="code-sample"> <span style="color: blue;"><</span><span style="color: maroon;">Widget</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Color"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Red"</span><span style="color: fuchsia;"> </span><span style="color: #FF0000">Color</span><span style="color: blue;">="Red" /></span></pre> </div> -<h4>Long Strings</h4> + <hr /> + <h2>Long Strings</h2> <p>There is an optional mode to define a property value inside a CDATA tag for very long strings like sql statements or Javascript templates. </p> @@ -150,7 +148,8 @@ <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">Property</span><span style="color: blue;">></span></pre> </div> - <h4>Enumeration Properties</h4> + <hr /> + <h2>Enumeration Properties</h2> <p>Enumeration arguments are defined the same way as primitive properties. Use the string names of the enumeration for the values.</p> @@ -181,7 +180,8 @@ <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt;"> <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: #800000">Instance</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Cow"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Maggie" </span><span style="color: #FF0000">Breed</span><span style="color: blue;">="Angus" /></span></pre> </div> - <h4>Child Properties</h4> + <hr /> + <h2>Child Properties</h2> <p>Child properties of non-primitive types are defined as embedded memento nodes. Child properties can be either defined inline or use a reference to a named instance of the @@ -229,7 +229,8 @@ <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">MyGrandChild</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Tommy"/></span></pre> <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">StructureMap.Testing.Widget.Child</span><span style="color: blue;">></span> </pre> </div> -<h3>Non Primitive Array Property</h3> + <hr /> + <h2>Non Primitive Array Property</h2> <p>If a property or constructor argument is an array of a non-primitive type, create a child node to the top level instance node with the name of the property. Simply add new InstanceMemento nodes with the name <Child> under the property @@ -258,8 +259,10 @@ <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: #800000">Child</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Random" </span><span style="color: #FF0000">seed</span><span style="color: blue;">="0.034"/></span></pre> <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">innerStrategies</span><span style="color: blue;">></span></pre> <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">Instance</span><span style="color: blue;">></span></pre> + <p style="margin: 0px;"> </p> + <hr /> </div> -<h3>Primitive Arrays</h3> +<h2>Primitive Arrays</h2> <p>Primitive arrays like string[] or int[] can be defined in Xml. For a class with arguments like:</p> <!-- @@ -284,7 +287,8 @@ <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 <\cf3 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\cf1 >\par ??\par ?? <\cf3 numbers\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1,2,3\cf0 "\cf1 />\par ?? <\cf3 strings\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1,2,3\cf0 "\cf1 />\par ?? </\cf3 DefaultInstance\cf1 >} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;" + class="code-sample"> <p style="margin: 0px;"> <span style="color: blue;"> <</span><span style="color: #a31515;">DefaultInstance</span></p> <p style="margin: 0px;"> @@ -321,7 +325,8 @@ <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 <\cf3 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\cf1 >\par ??\par ?? <\cf3 numbers\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1;2;3\cf0 "\cf1 \cf4 Delimiter\cf1 =\cf0 "\cf1 ;\cf0 "\cf1 />\par ?? <\cf3 strings\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1,2,3\cf0 "\cf1 />\par ?? </\cf3 DefaultInstance\cf1 >} --> -<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;" + class="code-sample"> <p style="margin: 0px;"> <span style="color: blue;"> <</span><span style="color: #a31515;">DefaultInstance</span></p> <p style="margin: 0px;"> @@ -352,14 +357,16 @@ style="color: blue;">></span></p> </div> <!--EndFragment--> -<h3>Dictionaries and NameValueCollection</h3> +<hr /> + <h2>Dictionaries and NameValueCollection</h2> <p>Any form of IDictionary<Key, Value> or a NameValueCollection can be configured in Xml by the following syntax. Say you have a class that needs a Dictionary of properties:</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassWithDictionary\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 IDictionary\cf0 <\cf3 string\cf0 , \cf3 string\cf0 > _dictionary;\par ??\par ?? \cf3 public\cf0 ClassWithDictionary(\cf4 IDictionary\cf0 <\cf3 string\cf0 , \cf3 string\cf0 > dictionary)\par ?? \{\par ?? _dictionary = dictionary;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf4 IDictionary\cf0 <\cf3 string\cf0 , \cf3 string\cf0 > Dictionary\par ?? \{\par ?? \cf3 get\cf0 \{ \cf3 return\cf0 _dictionary; \}\par ?? \}\par ?? \}} --> -<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white;" + class="code-sample"> <p style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;"> class</span> <span style="color: #2b91af;">ClassWithDictionary</span></p> @@ -410,7 +417,8 @@ <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 <\cf3 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithDictionary, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithDictionary, StructureMap.Testing\cf0 "\cf1 >\par ?? <\cf3 dictionary\cf1 >\par ?? <\cf3 Pair\cf1 \cf4 Key\cf1 =\cf0 '\cf1 color\cf0 '\cf1 \cf4 Value\cf1 =\cf0 '\cf1 red\cf0 '\cf1 />\par ?? <\cf3 Pair\cf1 \cf4 Key\cf1 =\cf0 '\cf1 state\cf0 '\cf1 \cf4 Value\cf1 =\cf0 '\cf1 texas\cf0 '\cf1 />\par ?? <\cf3 Pair\cf1 \cf4 Key\cf1 =\cf0 '\cf1 direction\cf0 '\cf1 \cf4 Value\cf1 =\cf0 '\cf1 north\cf0 '\cf1 />\par ?? </\cf3 dictionary\cf1 >\par ?? </\cf3 DefaultInstance\cf1 >} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;" + class="code-sample"> <p style="margin: 0px;"> <span style="color: blue;"> <</span><span style="color: #a31515;">DefaultInstance</span></p> <p style="margin: 0px;"> @@ -456,7 +464,7 @@ <p>Just create a new node for the IDictionary property called <[propertyName]> under the main instance node. Then add a <Pair Key="key" Value="value"/> node for each name/value pair in the IDictionary. </p> -<p> </p> + <hr /> </body> </html> Added: trunk/Source/HTML/AutoMocker.htm =================================================================== --- trunk/Source/HTML/AutoMocker.htm (rev 0) +++ trunk/Source/HTML/AutoMocker.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title></title> + </head> + <body> + + </body> +</html> \ No newline at end of file Added: trunk/Source/HTML/AutoWiring.htm =================================================================== --- trunk/Source/HTML/AutoWiring.htm (rev 0) +++ trunk/Source/HTML/AutoWiring.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -0,0 +1,461 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Auto Wiring</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> + </head> + <body> + <p> + The best way to use an IoC container is to allow "Auto Wiring" to do most of the + work for you. IoC Containers like StructureMap are an infrastructure + concern, and as such, should be isolated from as much of your code as possible. + Before examining Auto Wiring in depth, let's look at a common anti pattern of + IoC usage:</p> + <h2> + IoC Container Anti-Pattern</h2> + <p> + One of the worst, but sadly most common, usages of an IoC container is + shown below:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 // This is the way to write a Constructor Function with an IoC tool\par ??\cf0 \cf3 // Let the IoC container "inject" services from outside, and keep\par ??\cf0 \cf3 // ShippingScreenPresenter ignorant of the IoC infrastructure\par ??\cf0 \cf4 public\cf0 ShippingScreenPresenter(\cf5 IShippingService\cf0 service, \cf5 IRepository\cf0 repository)\par ?? \{\par ?? _service = service;\par ?? _repository = repository;\par ?? \}\par ??\par ?? \cf3 // FAIL!\par ??\cf0 \cf3 // This is the wrong way to use an IoC container. Do NOT invoke the container from\par ??\cf0 \cf3 // the constructor function. This tightly couples the ShippingScreenPresenter to\par ??\cf0 \cf3 // the IoC container in a harmful way. This class cannot be used in either\par ??\cf0 \cf3 // production or testing without a valid IoC configuration. Plus, you're writing more\par ??\cf0 \cf3 // code\par ??\cf0 \cf4 public\cf0 ShippingScreenPresenter()\par ?? \{\par ?? _service = \cf5 ObjectFactory\cf0 .GetInstance<\cf5 IShippingService\cf0 >();\par ?? _repository = \cf5 ObjectFactory\cf0 .GetInstance<\cf5 IRepository\cf0 >();\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: green;">// This is the way to + write a Constructor Function with an IoC tool</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// Let the IoC container + "inject" services from outside, and keep</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// + ShippingScreenPresenter ignorant of the IoC infrastructure</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ShippingScreenPresenter(<span style="color: #2b91af;">IShippingService</span> + service, <span style="color: #2b91af;">IRepository</span> repository)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _service = service;</p> + <p style="margin: 0px;"> + _repository = repository;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;">// FAIL!</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// This is the wrong way + to use an IoC container. Do NOT invoke the container from</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// the constructor + function. This tightly couples the ShippingScreenPresenter to</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// the IoC container in a + harmful way. This class cannot be used in either</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// production or testing + without a valid IoC configuration. Plus, you're writing more</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// code</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ShippingScreenPresenter()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _service = + <span style="color: #2b91af;">ObjectFactory</span>.GetInstance<<span + style="color: #2b91af;">IShippingService</span>>();</p> + <p style="margin: 0px;"> + _repository = + <span style="color: #2b91af;">ObjectFactory</span>.GetInstance<<span + style="color: #2b91af;">IRepository</span>>();</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> + <h2> + Example</h2> + <p> + Typically, you’ll try to + minimize the number of service locator[LINK] usages in your system to a bare minimum + (I found 8 in my current system, but I think I’ll find a way to prune half of + those later). Most of the value of an IoC tool is in automatically doing + Dependency Injection. I’m working with the new MVC framework at the + moment, so it’s a handy sample. Let’s say that we have a Controller class + for a typical CRUD screen. That Controller class will generally need to + interact with both validation services and the data access functionality of the + Repository. Here’s a representative Controller class:-RIGHT: black thin solid; BORDER-TOP: black thin solid; FONT-SIZE: 10pt; BACKGROUND: white; OVERFLOW: scroll; BORDER-LEFT: black thin solid; COLOR: black; BORDER-BOTTOM: black thin solid; FONT-FAMILY: courier new"> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> + <span style="COLOR: #2b91af">SomeScreenController</span> : + <span style="COLOR: #2b91af">IController</span></p> + <p style="MARGIN: 0px"> + {</p> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">private</span> + <span style="COLOR: blue">readonly</span> <span style="COLOR: #2b91af"> + IRepository</span> _repository;</p> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">private</span> + <span style="COLOR: blue">readonly</span> <span style="COLOR: #2b91af"> + IValidator</span> _validator;</p> + <p style="MARGIN: 0px"> + </p> + <p style="MARGIN: 0px"> + <span style="COLOR: green">// SomeScreenController + depends on both IRepository and IValidator</span></p> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">public</span> + SomeScreenController(<span style="COLOR: #2b91af">IRepository</span> repository, + <span style="COLOR: #2b91af">IValidator</span> validator)</p> + <p style="MARGIN: 0px"> + {</p> + <p style="MARGIN: 0px"> + _repository = repository;</p> + <p style="MARGIN: 0px"> + _validator = validator;</p> + <p style="MARGIN: 0px"> + }</p> + <p style="MARGIN: 0px"> + </p> + <p style="MARGIN: 0px"> + }</p> + </div> + <p> + So let’s get StructureMap set up for this SomeScreenController class:</p> + <div style="BORDER-RIGHT: black thin solid; BORDER-TOP: black thin solid; FONT-SIZE: 10pt; BACKGROUND: white; OVERFLOW: scroll; BORDER-LEFT: black thin solid; COLOR: black; BORDER-BOTTOM: black thin solid; FONT-FAMILY: courier new"> + <p style="MARGIN: 0px"> + <span style="COLOR: #2b91af"> + ObjectFactory</span>.Initialize(x =></p> + <p style="MARGIN: 0px"> + {</p> + <p style="MARGIN: 0px"> + + <span style="COLOR: green">// Set up the IValidator</span></p> + <p style="MARGIN: 0px"> + + x.ForRequestedType<<span style="COLOR: #2b91af">IValidator</span>>().TheDefaultIsConcreteType<<span + style="COLOR: #2b91af">Validator</span>>();</p> + <p style="MARGIN: 0px"> + </p> + <p style="MARGIN: 0px"> + + <span style="COLOR: green">// Set up the IRepository</span></p> + <p style="MARGIN: 0px"> + + x.ForRequestedType<<span style="COLOR: #2b91af">IRepository</span>>().TheDefault.Is.OfConcreteType<<span + style="COLOR: #2b91af">Repository</span>>()</p> + <p style="MARGIN: 0px"> + + .WithCtorArg(<span style="COLOR: #a31515">"connectionString"</span>).EqualToAppSetting(<span + style="COLOR: #a31515">"CONNECTION-STRING"</span>);</p> + <p style="MARGIN: 0px"> + });</p> + </div> + <p> + You’ll notice that we didn’t make any explicit configuration for the + SomeScreenController class, but yet we could now call:</p> + <div style="BORDER-RIGHT: black thin solid; BORDER-TOP: black thin solid; FONT-SIZE: 10pt; BACKGROUND: white; OVERFLOW: scroll; BORDER-LEFT: black thin solid; COLOR: black; BORDER-BOTTOM: black thin solid; FONT-FAMILY: courier new"> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">var</span> + controller = <span style="COLOR: #2b91af">ObjectFactory</span>.GetInstance<<span + style="COLOR: #2b91af">SomeScreenController</span>>();</p> + </div> + <p> + and StructureMap will happily create a new instance of the SomeScreenController + class by invoking its constructor and passing in a new Validator object and a + new Repository object created with the connection string from the App.config + file. We didn’t need to tell StructureMap how to construct + SomeScreenController because: + </p> + <ul> + <li>StructureMap can look at the constructor function of SomeScreenController and + see that it depends on IValidator and IRepository </li> + <li>StructureMap “knows” about the default way to create and return an IValidator + and an IRepository </li> + </ul> + <p> + This feature is known as “auto wiring,” and all the mainstream IoC containers + support this feature to some extent or another. + </p> + <hr /> + <h2>StructureMap's Policies for Auto Wiring</h2> + <p>By default, as long as an object is being created by invoking its constructor + function, StructureMap will try to create/resolve/find an object for each + non-primitive dependency in the requested concrete type. If StructureMap + doesn't "know" how to find a requested dependency, it will throw an exception. + By design, StructureMap cannot auto wire primitive arguments like strings and + numbers. The Auto Wiring can be overriden by explicit configuration (this + might actually be easier with Xml configuration):</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 registry.InstanceOf<\cf3 Rule\cf0 >()\par ?? .Is.OfConcreteType<\cf3 WidgetRule\cf0 >()\par ?? .WithName(\cf4 "TheWidgetRule"\cf0 )\par ?? .CtorDependency<\cf3 IWidget\cf0 >().Is(i => i.TheInstanceNamed(\cf4 "Yellow"\cf0 ));} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + registry.InstanceOf<<span style="color: #2b91af;">Rule</span>>()</p> + <p style="margin: 0px;"> + + .Is.OfConcreteType<<span style="color: #2b91af;">WidgetRule</span>>()</p> + <p style="margin: 0px;"> + + .WithName(<span style="color: #a31515;">"TheWidgetRule"</span>)</p> + <p style="margin: 0px;"> + + .CtorDependency<<span style="color: #2b91af;">IWidget</span>>().Is(i => + i.TheInstanceNamed(<span style="color: #a31515;">"Yellow"</span>));</p> + </div> +<!--EndFragment--> +<p>In the example above, the IWidget dependency of the WidgetRule class is + overriden.</p> + <hr /> + <h4>Object Identity within a Single Request</h4> + <p>TODO</p> + <hr /> + <h4>Injecting Arrays of Services</h4> + <p>TODO</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IValidator\par ??\cf0 \{\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Validator\cf0 : \cf4 IValidator\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf3 string\cf0 _name;\par ??\par ?? \cf3 public\cf0 Validator(\cf3 string\cf0 name)\par ?? \{\par ?? _name = name;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 override\cf0 \cf3 string\cf0 ToString()\par ?? \{\par ?? \cf3 return\cf0 \cf3 string\cf0 .Format(\cf5 "Name: \{0\}"\cf0 , _name);\par ?? \}\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassThatUsesValidators\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 IValidator\cf0 [] _validators;\par ??\par ?? \cf3 public\cf0 ClassThatUsesValidators(\cf4 IValidator\cf0 [] validators)\par ?? \{\par ?? _validators = validators;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 void\cf0 Write()\par ?? \{\par ?? \cf3 foreach\cf0 (\cf4 IValidator\cf0 validator \cf3 in\cf0 _validators)\par ?? \{\par ?? \cf4 Debug\cf0 .WriteLine(validator);\par ?? \}\par ?? \}\par ?? \}\par ??\par ?? [\cf4 TestFixture\cf0 ]\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 ValidatorExamples\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 Container\cf0 container;\par ??\par ?? [\cf4 SetUp\cf0 ]\par ?? \cf3 public\cf0 \cf3 void\cf0 SetUp()\par ?? \{\par ?? container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.ForRequestedType<\cf4 IValidator\cf0 >().AddInstances(o =>\par ?? \{\par ?? o.OfConcreteType<\cf4 Validator\cf0 >().WithCtorArg(\cf5 "name"\cf0 ).EqualTo(\cf5 "Red"\cf0 ).WithName(\cf5 "Red"\cf0 );\par ?? o.OfConcreteType<\cf4 Validator\cf0 >().WithCtorArg(\cf5 "name"\cf0 ).EqualTo(\cf5 "Blue"\cf0 ).WithName(\cf5 "Blue"\cf0 );\par ?? o.OfConcreteType<\cf4 Validator\cf0 >().WithCtorArg(\cf5 "name"\cf0 ).EqualTo(\cf5 "Purple"\cf0 ).WithName(\cf5 "Purple"\cf0 );\par ?? o.OfConcreteType<\cf4 Validator\cf0 >().WithCtorArg(\cf5 "name"\cf0 ).EqualTo(\cf5 "Green"\cf0 ).WithName(\cf5 "Green"\cf0 );\par ?? \});\par ??\par ?? x.ForRequestedType<\cf4 ClassThatUsesValidators\cf0 >().AddInstances(o =>\par ?? \{\par ?? \cf6 // Define an Instance of ClassThatUsesValidators that depends on AutoWiring\par ??\cf0 o.OfConcreteType<\cf4 ClassThatUsesValidators\cf0 >().WithName(\cf5 "WithAutoWiring"\cf0 );\par ??\par ?? \cf6 // Define an Instance of ClassThatUsesValidators that overrides AutoWiring\par ??\cf0 o.OfConcreteType<\cf4 ClassThatUsesValidators\cf0 >().WithName(\cf5 "ExplicitArray"\cf0 )\par ?? .TheArrayOf<\cf4 IValidator\cf0 >().Contains(y =>\par ?? \{\par ?? y.TheInstanceNamed(\cf5 "Red"\cf0 );\par ?? y.TheInstanceNamed(\cf5 "Green"\cf0 );\par ?? \});\par ?? \});\par ?? \});\par ?? \}\par ??\par ?? [\cf4 Test\cf0 ]\par ?? \cf3 public\cf0 \cf3 void\cf0 what_are_the_validators()\par ?? \{\par ?? \cf4 Debug\cf0 .WriteLine(\cf5 "With Auto Wiring"\cf0 );\par ?? container.GetInstance<\cf4 ClassThatUsesValidators\cf0 >(\cf5 "WithAutoWiring"\cf0 ).Write();\par ?? \cf4 Debug\cf0 .WriteLine(\cf5 "================================="\cf0 );\par ?? \cf4 Debug\cf0 .WriteLine(\cf5 "With Explicit Configuration"\cf0 );\par ?? container.GetInstance<\cf4 ClassThatUsesValidators\cf0 >(\cf5 "ExplicitArray"\cf0 ).Write();\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">interface</span> + <span style="color: #2b91af;">IValidator</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">Validator</span> : <span style="color: #2b91af;"> + IValidator</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">readonly</span> <span style="color: blue;">string</span> + _name;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> Validator(<span + style="color: blue;">string</span> name)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _name = name;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">override</span> <span style="color: blue;">string</span> + ToString()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> <span style="color: blue;">string</span>.Format(<span + style="color: #a31515;">"Name: {0}"</span>, _name);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">ClassThatUsesValidators</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">readonly</span> <span style="color: #2b91af;"> + IValidator</span>[] _validators;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ClassThatUsesValidators(<span style="color: #2b91af;">IValidator</span>[] + validators)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _validators = validators;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">void</span> Write()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + foreach</span> (<span style="color: #2b91af;">IValidator</span> validator + <span style="color: blue;">in</span> _validators)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: #2b91af;">Debug</span>.WriteLine(validator);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">TestFixture</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">ValidatorExamples</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: #2b91af;">Container</span> container;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">SetUp</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">void</span> SetUp()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + container = + <span style="color: blue;">new</span> <span style="color: #2b91af;">Container</span>(x + =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.ForRequestedType<<span style="color: #2b91af;">IValidator</span>>().AddInstances(o + =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Red"</span>).WithName(<span + style="color: #a31515;">"Red"</span>);</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Blue"</span>).WithName(<span + style="color: #a31515;">"Blue"</span>);</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Purple"</span>).WithName(<span + style="color: #a31515;">"Purple"</span>);</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Green"</span>).WithName(<span + style="color: #a31515;">"Green"</span>);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + x.ForRequestedType<<span style="color: #2b91af;">ClassThatUsesValidators</span>>().AddInstances(o + =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: green;">// Define an Instance of ClassThatUsesValidators + that depends on AutoWiring</span></p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">ClassThatUsesValidators</span>>().WithName(<span + style="color: #a31515;">"WithAutoWiring"</span>);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// Define an Instance of ClassThatUsesValidators + that overrides AutoWiring</span></p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">ClassThatUsesValidators</span>>().WithName(<span + style="color: #a31515;">"ExplicitArray"</span>)</p> + <p style="margin: 0px;"> + + .TheArrayOf<<span style="color: #2b91af;">IValidator</span>>().Contains(y =></p> + <p style="margin: 0px;"> + + {</p> + <p style="margin: 0px;"> + + y.TheInstanceNamed(<span style="color: #a31515;">"Red"</span>);</p> + <p style="margin: 0px;"> + + y.TheInstanceNamed(<span style="color: #a31515;">"Green"</span>);</p> + <p style="margin: 0px;"> + + });</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">Test</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">void</span> what_are_the_validators()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"With Auto Wiring"</span>);</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">ClassThatUsesValidators</span>>(<span + style="color: #a31515;">"WithAutoWiring"</span>).Write();</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"================================="</span>);</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"With Explicit + Configuration"</span>);</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">ClassThatUsesValidators</span>>(<span + style="color: #a31515;">"ExplicitArray"</span>).Write();</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p> </p> + <p> </p> + <hr /> + </body> +</html> \ No newline at end of file Copied: trunk/Source/HTML/ChangingConfigurationAtRuntime.htm (from rev 204, trunk/Source/HTML/InjectingServicesAtRuntime.htm) =================================================================== --- trunk/Source/HTML/ChangingConfigurationAtRuntime.htm (rev 0) +++ trunk/Source/HTML/ChangingConfigurationAtRuntime.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -0,0 +1,405 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Changing Configuration at Runtime</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> + </head> + <body> + <p>In the beginning (late 2003), there was attributes and there was a copious amount of Xml configuration, and I called it good. + Look Ma! I can radically change the behavior of the code without + recompiling, isn't that a marvelous thing? + Then we started to use StructureMap on a real project and quickly realized that + it would be very useful if we could override some services with mock objects in + our unit tests. In later projects I've run into scenarios where it would + be valuable to put an object into StructureMap after it was created. Other + users have asked for the ability to load assemblies or modules of their system + on demand so as to save memory. A major goal of the StructureMap 2.5 + release has been to greatly extend its capabilities for service registration at + runtime. With a very few exceptions, you can now make any and all + configuration changes after the first call to ObjectFactory. My + recommendation is to use this behavior simply and with caution because it will + bypass many of the diagnostic abilities built into StructureMap (i.e. + StructureMapDoctor might miss configuration problems introduced outside of the + normal configuration).</p> +<h2> + Adding Configuration to an Existing Container</h2> +<p> + In contrast to Initialize(), the Configure() method allows you to add additional + configuration to an existing Container or ObjectFactory. Think of this + scenario. You're building a composite application that contains multiple + modules spread over several assemblies, but you might not want to load any of + the configuration or types for a particular module until it's requested by the + user. In that case, you can use the Configure() method like this:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 // This code would add any configuration from\par ??\cf0 \cf3 // Registry classes found in the \par ??\cf0 \cf3 // assembly named 'MyApplication.Module1'\par ??\cf0 \cf4 ObjectFactory\cf0 .Configure(x =>\par ?? \{\par ?? x.Scan(scan =>\par ?? \{\par ?? scan.LookForRegistries();\par ?? scan.Assembly(\cf5 "MyApplication.Module1"\cf0 );\par ?? \});\par ?? \});} +--> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid; overflow: scroll;"> + <p style="margin: 0px;"> + + <span style="color: green;">// This code would add any configuration from</span></p> + <p style="margin: 0px;"> + + <span style="color: green;">// Registry classes found in the </span> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// assembly named 'MyApplication.Module1'</span></p> + <p style="margin: 0px;"> + + <span style="color: #2b91af;">ObjectFactory</span>.Configure(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + ... [truncated message content] |
From: <jer...@us...> - 2009-01-05 04:28:02
|
Revision: 216 http://structuremap.svn.sourceforge.net/structuremap/?rev=216&view=rev Author: jeremydmiller Date: 2009-01-05 04:27:51 +0000 (Mon, 05 Jan 2009) Log Message: ----------- more documentation Modified Paths: -------------- trunk/Source/HTML/AutoWiring.htm trunk/Source/HTML/ChangingConfigurationAtRuntime.htm trunk/Source/HTML/Concepts.htm trunk/Source/HTML/ConfiguringStructureMap.htm trunk/Source/HTML/Default.htm trunk/Source/HTML/Generics.htm trunk/Source/HTML/Glossary.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/InstanceExpression.htm trunk/Source/HTML/Menu.htm trunk/Source/HTML/NodeNormalized.htm trunk/Source/HTML/RegistryDSL.htm trunk/Source/HTML/RetrievingServices.htm trunk/Source/HTML/ScanningAssemblies.htm trunk/Source/HTML/UsingSessionContext.htm trunk/Source/HTML/style.css Added Paths: ----------- trunk/Source/HTML/DependencyInjection.htm trunk/Source/HTML/InversionOfControl.htm Modified: trunk/Source/HTML/AutoWiring.htm =================================================================== --- trunk/Source/HTML/AutoWiring.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/AutoWiring.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -82,7 +82,9 @@ <h2> Example</h2> <p> - Typically, you’ll try to minimize the number of service locator[LINK] usages in + Typically, you’ll try to minimize the number of + <a href="%20%20%20%20%20%20%20%20%20%20%20%20Typically,%20you’ll%20try%20to%20minimize%20the%20number%20of%20Service%20Locator%20usages%20in%20">Service Locator</a> + (Container.Get*****) usages in your system to a bare minimum (I found 8 in my current system, but I think I’ll find a way to prune half of those later). Most of the value of an IoC tool is in automatically doing Dependency Injection. I’m working with the new Modified: trunk/Source/HTML/ChangingConfigurationAtRuntime.htm =================================================================== --- trunk/Source/HTML/ChangingConfigurationAtRuntime.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/ChangingConfigurationAtRuntime.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -259,8 +259,8 @@ functionality in favor of the simple ObjectFactory/Container.Inject<T>(T object) methods.</p> <p>My strong advice is to not use the Container or ObjectFactory in unit tests in - the mass majority of cases. Rather, my advice is to use simple Dependency - Injection[LINK] to inject mock objects during unit tests. However, there + the mass majority of cases. Rather, my advice is to use simple + <a href="DependencyInjection.htm">Dependency Injection</a> to inject mock objects during unit tests. However, there are still times when you want or need a class to use the Container or ObjectFactory itself to get dependencies at runtime. For that case, here is a sample:</p> Modified: trunk/Source/HTML/Concepts.htm =================================================================== --- trunk/Source/HTML/Concepts.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/Concepts.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -1,9 +1,438 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>Software Design Concepts</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> + <p> + Before you jump into using StructueMap in anger, there are some design concepts + that can help you get the most out of an IoC tool. This web page is + strictly about conceptual design fundamentals, and not particularly specific to + StructureMap itself. I think this stuff is important to real world + development. You might not memorize the "Liskov Substitution Principle" + text, but you're code will be better for following its intent -- even if you + don't particulary know the exact term for LSP. When you read this section, + please focus on the concepts and any class's role within a system rather than + get caught up in coding details like "why is he using an AddressController + instead of that being part of another class?"</p> + <p> + </p> + <h2> + Design Concepts</h2> + <p> + Over the years a series of concepts and principles have been discovered and + developed to describe well-structured Object Oriented systems. To most + effectively use StructureMap, or any other IoC tool for that matter, your system + needs to be designed with these principles first: + </p> + <ul> + <li><a href="http://en.wikipedia.org/wiki/Separation_of_concerns" + mce_href="http://en.wikipedia.org/wiki/Separation_of_concerns">Separation of + Concerns</li> + <li><a href="http://msdn.microsoft.com/en-us/magazine/cc546578.aspx" + mce_href="http://msdn.microsoft.com/en-us/magazine/cc546578.aspx">Open + Closed Principle, the Single Responsibility Principle, and the Liskov + Substitution Principle</a></li> + <li><a href="http://codebetter.com/blogs/jeremy.miller/pages/129542.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/pages/129542.aspx"> + Responsibilities, Cohesion, and Coupling</a></li> + <li><a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/01/08/Orthogonal-Code.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/archive/2007/01/08/Orthogonal-Code.aspx"> + Orthogonal Code</a></li> + <li><a href="http://codebetter.com/blogs/jeremy.miller/pages/129543.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/pages/129543.aspx"> + Dependency Inversion Principle</a></li> + <li><a href="http://www.artima.com/lejava/articles/designprinciples4.html" + mce_href="http://www.artima.com/lejava/articles/designprinciples4.html"> + Favor Composition over Inheritance</a></li> + </ul> + <p> + To sum it all up, well designed Object Oriented systems are <b>composed</b> of + many objects that work with each other to accomplish to goals of the system. + We want our systems to be decomposed into cohesive classes that perform a well + defined responsibility within the system, rather than monolithic “God” classes + that do too much. A cohesive class will have to be dependent upon other + classes to perform services outside of its own tightly defined responsibility. + In IoC speak, we call the collaborating objects <b>dependencies</b>. + </p> + <hr /> + <h2 class="style1"> + Dependencies</h2> + <p> + For example, in my current system we have a class called + <font face="Courier New">AddressEditController</font> that governs the creation + and editing of Address entities in our web based UI. The + AddressEditController needs to validate user input and persist or load data. + Those are two distinct responsibilities, so AddressEditController has + dependencies on other objects for these services. + </p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: rgb(43, 145, 175);">AddressEditController</span> : + <span style="color: rgb(43, 145, 175);">Controller</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;">// AddressEditController + uses IValidator to validate user input</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// and IRepository to + load and save Address information</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">readonly</span> + <span style="color: rgb(43, 145, 175);">IValidator</span> _validator;</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: rgb(43, 145, 175);">IRepository</span> _repository;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + So here’s some facts about <font face="Courier New">AddressEditController:</font></p> + <ul> + <li><font face="Courier New">AddressEditController</font> depends on + <font face="Courier New">IValidator</font> and <font face="Courier New"> + IRepository</font> </li> + <li><font face="Courier New">AddressEditController</font> cannot function unless it + has both an <font face="Courier New">IValidator</font> and an + <font face="Courier New">IRepository</font></li> + <li>From the concepts section above, for best results, the <font face="Courier New"> + AddressEditController</font> should be loosely coupled to its dependencies by + knowing as little about the inner workings of the real <font face="Courier New"> + IValidator</font> and <font face="Courier New">IRepository</font></li> + <li>The real IRepository is a Gateway into NHibernate. The concrete Repository class + cannot be used without its own dependency trail of external configuration, a + Singleton to keep track of an expensive resource, and some NHibernate + bootstrapping code. </li> + </ul> + <p> + Just calling a new() constructor on its dependencies isn’t the best design for + our <font face="Courier New">AddressEditController</font>. Creating a + concrete Validator class is very possible, but what if we want to selectively + replace the implementation of IValidator later? That’s only somewhat + likely, but the dependency on Repository is a much larger concern. I might + have semantic decoupling between <font face="Courier New">AddressEditController</font> + and Repository, but if <font face="Courier New">AddressEditController</font> + calls new Repository() itself, <font face="Courier New">AddressEditController</font> + will not be able to function without all that NHibernate bootstrapping. I + do not want a piece of my user interface to be tightly coupled to the existence + of the persistence layer. + </p> + <p> + In other scenarios, creating the dependencies may involve more than just calling + new() on the dependencies (don’t believe me? Go try to create an + HttpContext object).</p> + <p> + <font face="Courier New">AddressEditController</font> is responsible for the + workflow around editing Address entities in the UI. It shouldn’t be + concerned with NHibernate configuration and whatnot. One way to solve this + problem is to move the responsibility for building its dependencies to somewhere + external to <font face="Courier New">AddressEditController</font>. + </p> + <hr /> + <h2> + Inversion of Control and Dependency Injection</h2> + <p> + In many cases, I don’t want my classes to have to be aware of how their + dependencies are created or located. I don’t want controller classes to + even care that they’re using an object that is created via Microsoft’s Provider + infrastructure, or a Singleton, or needs configuration data. My class + should only know the public interfaces of its dependencies. I can make + that true by applying “<a + href="http://codebetter.com/blogs/jeremy.miller/archive/2005/09/20/132290.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/archive/2005/09/20/132290.aspx">Inversion + of Control</a>.” Instead of doing:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + AddressEditController()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _validator = + <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);"> + Validator</span>();</p> + <p style="margin: 0px;"> + _repository = + <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);"> + Repository</span>();</p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + where <font face="Courier New">AddressEditController</font> calls linearly + through to the constructors on Validator and Repository, we can invert the + control to make the creator of <font face="Courier New">AddressEditController</font> + responsible for building the dependencies and “pushing” them into + <font face="Courier New">AddressEditController</font>. + </p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: rgb(43, 145, 175);">AddressEditController</span> : + <span style="color: rgb(43, 145, 175);">Controller</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + </p> + <span style="color: blue;">private</span> <span style="color: blue;"> + readonly</span> <span style="color: rgb(43, 145, 175);">IValidator</span> + _validator; + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: rgb(43, 145, 175);">IRepository</span> _repository;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + AddressEditController(<span style="color: rgb(43, 145, 175);">IValidator</span> + validator, <span style="color: rgb(43, 145, 175);">IRepository</span> + repository)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _validator = validator;</p> + <p style="margin: 0px;"> + _repository = repository;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + The code sample above uses a form of Inversion of Control called + <a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx"> + Dependency Injection</a> to push in the dependencies via a constructor function. + Of course, at some point, something needs to know how to create the entire chain + of dependencies and do all of that Dependency Injection. StructureMap + supports a pattern known as + <a href="http://martinfowler.com/articles/injection.html#UsingAServiceLocator" + mce_href="http://martinfowler.com/articles/injection.html#UsingAServiceLocator"> + Service Locator</a>:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Creates an AddressEditController with all of its dependencies</span></p> + <p style="margin: 0px;"> + + <span style="color: rgb(43, 145, 175);">AddressEditController</span> controller + = <span style="color: rgb(43, 145, 175);">ObjectFactory</span>.GetInstance<<span + style="color: rgb(43, 145, 175);">AddressEditController</span>>();</p> + </div> + <p> + <font face="Courier New">ObjectFactory</font> is a StructureMap class that + serves as a well known place to go and find any service that you need. + When the <font face="Courier New">AddressEditController</font> is created and + returned by <font face="Courier New">ObjectFactory</font>, it should be + completely ready to go. There’s another important concept to understand + before you use StructureMap. + </p> + <hr /> + <h2> + Auto Wiring</h2> + <p> + Every "real" IoC container supports the concept of "Auto Wiring." Auto + Wiring simply means that StructureMap can figure out dependency chains for you + without a lot of explicit configuration. When you ask for + <font face="Courier New">AddressEditController</font>, there is more going on + than just <font face="Courier New">AddressEditController</font> and its two + dependencies. The Repository class itself has its own dependencies.</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + [<span style="color: rgb(43, 145, 175);">DefaultConstructor</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> Repository(<span + style="color: rgb(43, 145, 175);">ISessionSource</span> source) : + <span style="color: blue;">this</span>(source.CreateSession())</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + In turn, the concrete version of <font face="Courier New">ISessionSource</font> + above has <b>its</b> own dependencies:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + SessionSource(<span style="color: rgb(43, 145, 175);">IDictionary</span><<span + style="color: blue;">string</span>, <span style="color: blue;">string</span>> + properties, <span style="color: rgb(43, 145, 175);">PersistenceModel</span> + model)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _configuration = + <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);"> + Configuration</span>();</p> + <p style="margin: 0px;"> + + _configuration.AddProperties(properties);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + model.Configure(_configuration);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + _sessionFactory = + _configuration.BuildSessionFactory();</p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + which starts to get interesting because <font face="Courier New">SessionSource</font> + needs some information like connection strings that have to come in from Xml + configuration: + </p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;"><</span><span style="color: rgb(163, 21, 21);">StructureMap</span><span + style="color: blue;"> </span><span style="color: red;">MementoStyle</span><span + style="color: blue;">=</span>"<span style="color: blue;">Attribute</span>"<span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">DefaultInstance</span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </span><span style="color: red;"> + PluginType</span><span style="color: blue;">=</span>"<span style="color: blue;">ShadeTree.DomainModel.ISessionSource,ShadeTree.DomainModel</span>"</p> + <p style="margin: 0px;"> + <span style="color: blue;"> </span><span style="color: red;"> + PluggedType</span><span style="color: blue;">=</span>"<span + style="color: blue;">ShadeTree.DomainModel.SessionSource,ShadeTree.DomainModel</span>"<span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">properties</span><span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">connection.provider</span>"<span style="color: blue;"> + </span><span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">NHibernate.Connection.DriverConnectionProvider</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">connection.driver_class</span>"<span + style="color: blue;"> </span><span style="color: red;">Value</span><span + style="color: blue;">=</span>"<span style="color: blue;">NHibernate.Driver.SqlClientDriver</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">dialect</span>"<span style="color: blue;"> </span> + <span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">NHibernate.Dialect.MsSql2000Dialect</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">hibernate.dialect</span>"<span style="color: blue;"> + </span><span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">NHibernate.Dialect.MsSql2000Dialect</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">use_outer_join</span>"<span style="color: blue;"> + </span><span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">true</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">connection.connection_string</span>"<span + style="color: blue;"> </span><span style="color: red;">Value</span><span + style="color: blue;">=</span>"<span style="color: blue;">a connection string + that I’m certainly not giving out to you!</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">show_sql</span>"<span style="color: blue;"> </span> + <span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">true</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </</span><span + style="color: rgb(163, 21, 21);">properties</span><span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </</span><span + style="color: rgb(163, 21, 21);">DefaultInstance</span><span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"></</span><span style="color: rgb(163, 21, 21);">StructureMap</span><span + style="color: blue;">></span></p> + </div> + <p> + Here’s some of the configuration for the other services that the entire + EditAddressController needs:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: rgb(43, 145, 175);">IValidator</span>>().TheDefaultIsConcreteType<<span + style="color: rgb(43, 145, 175);">Validator</span>>();</p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: rgb(43, 145, 175);">IRepository</span>>().TheDefaultIsConcreteType<<span + style="color: rgb(43, 145, 175);">Repository</span>>().CacheBy(<span + style="color: rgb(43, 145, 175);">InstanceScope</span>.Hybrid);</p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: rgb(43, 145, 175);">PersistenceModel</span>>().TheDefaultIsConcreteType<<span + style="color: rgb(43, 145, 175);">DovetailPersistenceModel</span>>();</p> + </div> + <p> + At no point did I specify that <font face="Courier New">EditAddressController</font> + needs an <font face="Courier New">IRepository</font> that needs an + <font face="Courier New">ISessionSource</font> that needs 2-3 other things, but + yet when I call:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Creates an AddressEditController with all of its dependencies</span></p> + <p style="margin: 0px;"> + + <span style="color: rgb(43, 145, 175);">AddressEditController</span> controller + = <span style="color: rgb(43, 145, 175);">ObjectFactory</span>.GetInstance<<span + style="color: rgb(43, 145, 175);">AddressEditController</span>>();</p> + </div> + <p> + StructureMap will construct <font face="Courier New">EditAddressController</font> + that had a new instance of <font face="Courier New">Repository</font> that had a + new instance of <font face="Courier New">SessionSource</font> that had an + <font face="Courier New">IDictionary<string, string></font> object and a new + instance of <font face="Courier New">DovetailPersistenceModel</font>. I + don’t have to explicitly tell StructureMap to do that for me because it uses its + “Auto Wiring” feature to examine the dependencies of each concrete class and act + accordingly. StructureMap does need to know what to do with each type of + object it encounters. When it tries to build the <font face="Courier New"> + Repository</font> class StructureMap sees the constructor argument for + <font face="Courier New">ISessionSource</font> on <font face="Courier New"> + Repository</font>, and knows to build and inject a new <font face="Courier New"> + SessionSource</font> object (and so on as deep as you need to go).</p> + </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/ConfiguringStructureMap.htm =================================================================== --- trunk/Source/HTML/ConfiguringStructureMap.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/ConfiguringStructureMap.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -15,7 +15,8 @@ else from the initial releases to StructureMap 2.5+. You have three forms of configuration to choose from:</p> <ol> - <li><a href="RegistryDSL.htm">Registry DSL</a> -- The programmatic Fluent Interface[LINK] API for configuring the Container in code.</li> + <li><a href="RegistryDSL.htm">Registry DSL</a> -- The programmatic + <a href="http://www.martinfowler.com/bliki/FluentInterface.html">Fluent Interface</a> API for configuring the Container in code.</li> <li><a href="XmlConfiguration.htm">Xml configuration</a> (StructureMap.config, the App.config file, or named files)</li> <li><a href="UsingAttributes.htm">StructureMap Attributes </a>-- Not fully deprecated, but not really recommended either. </li> </ol> Modified: trunk/Source/HTML/Default.htm =================================================================== --- trunk/Source/HTML/Default.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/Default.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -10,7 +10,7 @@ <p> StructureMap is a <a href="http://www.martinfowler.com/articles/injection.html">Dependency - Injection</a> / Inversion of Control[LINK] tool for .Net that can be used to improve the architectural + Injection</a> / <a href="InversionOfControl.htm">Inversion of Control</a> tool for .Net that can be used to improve the architectural qualities of an object oriented system by reducing the mechanical costs of good design techniques. StructureMap can enable looser coupling between classes and their dependencies, improve the testability of a class structure, and provide @@ -40,25 +40,30 @@ <p>Do not use StructureMap if an application or process requires little flexibility. The abstraction and indirection afforded by StructureMap is unnecessary and even harmful in simpler systems or processes. </p> - <h3>Status</h3> + <p>The easiest way to get started is with the <a href="QuickStart.htm">StructureMap + QuickStart</a>. Please send any questions or suggestions to the + <a href="http://groups.google.com/group/structuremap-users/post?hl=en"> + StructureMap User Group</a> on Google Groups.</p> + <p> </p> + <h2>Status</h2> <p>StructureMap is the oldest IoC/DI tool for .Net development and has been used in multiple production systems since June 2004. The current version 2.5.2 was released in January 2009, with a - 2.6 release scheduled no later than the end of January 2009. StructureMap is + 2.6 release scheduled for no later than the end of January 2009. StructureMap is primarily maintained and developed by <a href="mailto:jer...@ya...?subject=StructureMap">Jeremy D. Miller</a>, <a href="http://codebetter.com/blogs/jeremy.miller">The - Shade Tree Developer</a> and Joshua Flanagan [LINK] with other contributions from + Shade Tree Developer</a> and + <a href="http://www.lostechies.com/blogs/joshuaflanagan/default.aspx">Joshua Flanagan</a> with other contributions from the community.</p> <hr /> - <h2> - <strong>Related Links:</strong></h2> + <h2>Related Links:</h2> <ul> <li><a href="http://flimflan.com/blog/HelloStructureMap.aspx">Hello StructureMap</a> </li> <li><a href="http://frickinsweet.com/ryanlanciaux.com/post/Very-Quick-and-Simple-Dependency-Injection-with-StructureMap.aspx"> Very Quick and Simple Dependency Injection with StructureMap</a> </li> - <li><a href="http://dimecasts.net/Casts/ByTag/StructureMap">StructureMap on + <li><a href="http://dimecasts.net/Casts/ByTag/StructureMap">StructureMap ScreenCasts on DimeCasts</a> </li> <li><a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/10/25/initializing-and-configuring-a-structuremap-container.aspx"> Initializing and Configuring a StructureMap Container</a> </li> @@ -88,7 +93,7 @@ Integrating StructureMap with WCF</a> </li> </ul> - <p> </p> + <hr /> <p> </p> </body> Added: trunk/Source/HTML/DependencyInjection.htm =================================================================== --- trunk/Source/HTML/DependencyInjection.htm (rev 0) +++ trunk/Source/HTML/DependencyInjection.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -0,0 +1,1076 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Dependency Injection - What is it, and what is it good for?</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> + <style type="text/css"> + .style1 + { + font-weight: normal; + } + </style> + </head> + <body> + + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + This was originally posted on + <a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx">Jeremy's blog</a> way back in 2005. A few things + have changed, specifically the possibility of using mocking tools that can mock + concrete classes and mock without using Dependency Injection (DI) -- but Jeremy + still thinks it's much cleaner to use DI ;-)</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + </p> + <h2 style="margin: 0in 0in 0pt;"> + Dependency Injection</h2> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + Dependency Injection is a specific usage of the larger + <a href="InversionOfControl.htm">Inversion of Control</a> concept.<span style=""> </span>In a nutshell, dependency injection + just means that a given class or system is no longer responsible for + instantiating their own dependencies.<span style=""> </span>In this case + “Inversion of Control” refers to moving the responsibility for locating and + attaching dependency objects to another class or a DI tool.<span style=""> + </span>That might not sound that terribly profound, but it opens the door for a + lot of interesting scenarios.</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + While there’s a fair amount of unnecessary buzz and hype about the concept, I’ve + found Dependency Injection to be very advantageous for doing Test Driven + Development without pulling your hair out.<span style=""> </span>If you’ve + seen articles or blog posts about Dependency Injection but don’t quite + internalize the value of DI yet, here are the facts as I see them:</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <ol style="margin-top: 0in;" type="1"> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Dependency Injection is an + important pattern for creating classes that are easier to unit test in isolation</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Promotes loose coupling between + classes and subsystems </li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Adds potential flexibility to a + codebase for future changes</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Can enable better code reuse</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;"><b style="">The implementation is + simple and does *not* require a fancy DI tool<o:p></o:p></b></li> + </ol> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + The <a href="http://picocontainer.org/" mce_href="http://picocontainer.org/"> + PicoContainer</a> team even has silly tee shirts printed up that say “I expected + a paradigm shift, but all I got was a lousy constructor function.”<span + style=""> </span>DI is certainly a case where a minimum of effort + supplies quite a bit of benefit.<span style=""> </span>Don’t blow it off + just because it seems trivial.<span style=""> </span> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + There are tools out there that do Dependency Injection in .Net.<span style=""> + </span>I use my own tool called <a href="http://structuremap.sourceforge.net/" + mce_href="http://structuremap.sourceforge.net/">StructureMap</a> in my + development, but I’m going to focus on only the concept of DI in this post.</p> + <hr /> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <h2 style="margin: 0in 0in 0pt;"> + <b style="">Example Problem<o:p></o:p></b></h2> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <b style=""><o:p> </o:p></b></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + My first experience with conscious usage of DI was a WinForms client + communicating with the backend via web services that was built with the + <a href="http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx"> + Model View Presenter</a> (“Humble Dialog Box”) architecture for easier unit + testing.<span style=""> </span>Most screens in the client end up with + something like this set of classes:</p> + <ul style="margin-top: 0in;" type="disc"> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Model – Whatever business + object/DataSet/chunk of data is being displayed or edited</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">View – A WinForms UserControl + class.<span style=""> </span>Displays data to a user and captures user input + and screen events (duh).</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Service – A web service proxy + class to send requests to the backend</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Presenter – The controller class + that coordinates all of the above.</li> + </ul> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + The presenter class without Dependency Injection might look like this.</p> + <div class="code-sample"> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;">class</span> + Presenter<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">private</span> View _view;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">private</span> Model _model;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> Presenter(){}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;"> + object</span> CreateView(Model model)<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_model = model;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_view = <span style="color: blue;">new</span> View();<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_view.DisplayModel(model);<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">return</span> _view;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;">void</span> + Close()<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">bool</span> canClose = + <span style="color: blue;">true</span>;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><o:p></o:p></span> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">if</span> (_view.IsDirty())<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>canClose = _view.CanCloseDirtyScreen();<span style=""> </span><o:p></o:p> + </span> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">if</span> (canClose)<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_view.Close();<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;">void</span> + Save()<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>Service service = <span style="color: blue;">new</span> Service();<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>service.Persist(_model);<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}</span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + +</div> + + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + This code cannot be unit tested in isolation because it has a tight coupling to + a concrete implementation of both the WinForms UserControl (View) and the proxy + class to a web service (Service).<span style=""> </span>This code as is + cannot function without both the User Interface and a web server running the + backend.<span style=""> </span>The point of using the MVP is to + isolate most of the user interface logic away from the WinForms and web service + mechanics to enable effective unit testing, so we’re missing something here.<span + style=""> </span>To unit test the presenter logic we’d like to replace + the user interface and web service dependencies with a + <a href="http://martinfowler.com/articles/mocksArentStubs.html" + mce_href="http://martinfowler.com/articles/mocksArentStubs.html">Mock</a> + object inside our test fixture classes.<span style=""> </span>In order to + mock the view and service, we first need to use the + <a href="http://codebetter.com/blogs/jeremy.miller/articles/129543.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/articles/129543.aspx"> + Dependency Inversion Principle</a> to make the + <span style="font-family: 'Courier New';">Presenter</span> class depend on an + abstracted <span style="font-family: 'Courier New';">IView</span> and + <span style="font-family: 'Courier New';">IService</span> interface instead of + the concrete <span style="font-family: 'Courier New';">UserControl</span> and + <span style="font-family: 'Courier New';">WebProxy</span> classes.<span + style=""> </span>The next thing to do is to alter the + <span style="font-family: 'Courier New';">Presenter</span> class so that we can + substitute at run time the mock objects instead of the concrete classes within + the unit tests.<span style=""> </span>This is where Dependency Injection + comes into play.</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + There are a couple of different flavors of Dependency Injection (via + <a href="http://martinfowler.com/articles/injection.html" + mce_href="http://martinfowler.com/articles/injection.html">Martin Fowler</a> + + the Pico guys)</p> + <ol style="margin-top: 0in;" type="1"> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Constructor Injection – Attach + the dependencies through a constructor function at object creation</li> + <li class... [truncated message content] |
From: <jer...@us...> - 2009-01-08 13:29:03
|
Revision: 217 http://structuremap.svn.sourceforge.net/structuremap/?rev=217&view=rev Author: jeremydmiller Date: 2009-01-08 13:28:57 +0000 (Thu, 08 Jan 2009) Log Message: ----------- documentation update Modified Paths: -------------- trunk/Source/HTML/AttributeNormalized.htm trunk/Source/HTML/AutoMocker.htm trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/HTML/Diagnostics.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/HowDoesStructureMapWork.htm trunk/Source/HTML/Interception.htm trunk/Source/HTML/Menu.htm trunk/Source/HTML/NodeNormalized.htm trunk/Source/HTML/ScanningAssemblies.htm trunk/Source/HTML/XmlConfiguration.htm trunk/Source/HTML/XmlReference.htm Removed Paths: ------------- trunk/Source/HTML/ModularConfiguration.htm Modified: trunk/Source/HTML/AttributeNormalized.htm =================================================================== --- trunk/Source/HTML/AttributeNormalized.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/AttributeNormalized.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -5,6 +5,12 @@ <link rel="stylesheet" type="text/css" href="style.css" /> <script type="text/javascript" src="jquery-1.2.6.js"></script> <script type="text/javascript" src="structuremap.js"></script> + <style type="text/css"> + .style1 + { + font-weight: normal; + } + </style> </head> <body class="code"> <p>This style is a more terse configuration format that was @@ -12,7 +18,7 @@ Xml configuration by marking the <StructureMap> node with the MementoStyle="Attribute" attribute by default anytime you are using Xml configuration. </p> - <h2>Instance Root Node</h2> + <h2 class="style1">Instance Root Node</h2> <p>An Instance is defined in Xml starting from a root node. The actual name of the root node varies depending upon the context that an Instance is being configured. For example, the AddInstance, DefaultInstance, @@ -109,7 +115,7 @@ </div> <!--EndFragment--> <hr /> - <h2>Primitive Properties (Strings and basic value types)</h2> + <h2 class="style1">Primitive Properties (Strings and basic value types)</h2> <p>Primitive constructor or setter arguments are defined by adding an attribute @propertyName="propertyValue" to the instance node. A class with a string argument to the constructor,</p> @@ -131,7 +137,7 @@ </div> <hr /> - <h2>Long Strings</h2> + <h2 class="style1">Long Strings</h2> <p>There is an optional mode to define a property value inside a CDATA tag for very long strings like sql statements or Javascript templates. </p> @@ -149,7 +155,7 @@ </div> <hr /> - <h2>Enumeration Properties</h2> + <h2 class="style1">Enumeration Properties</h2> <p>Enumeration arguments are defined the same way as primitive properties. Use the string names of the enumeration for the values.</p> @@ -181,7 +187,7 @@ <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: #800000">Instance</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Cow"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Maggie" </span><span style="color: #FF0000">Breed</span><span style="color: blue;">="Angus" /></span></pre> </div> <hr /> - <h2>Child Properties</h2> + <h2 class="style1">Dependency Properties</h2> <p>Child properties of non-primitive types are defined as embedded memento nodes. Child properties can be either defined inline or use a reference to a named instance of the @@ -230,7 +236,7 @@ <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">StructureMap.Testing.Widget.Child</span><span style="color: blue;">></span> </pre> </div> <hr /> - <h2>Non Primitive Array Property</h2> + <h2 class="style1">Non Primitive Array Property</h2> <p>If a property or constructor argument is an array of a non-primitive type, create a child node to the top level instance node with the name of the property. Simply add new InstanceMemento nodes with the name <Child> under the property @@ -262,7 +268,7 @@ <p style="margin: 0px;"> </p> <hr /> </div> -<h2>Primitive Arrays</h2> +<h2 class="style1">Primitive Arrays</h2> <p>Primitive arrays like string[] or int[] can be defined in Xml. For a class with arguments like:</p> <!-- @@ -358,7 +364,7 @@ </div> <!--EndFragment--> <hr /> - <h2>Dictionaries and NameValueCollection</h2> + <h2 class="style1">Dictionaries and NameValueCollection</h2> <p>Any form of IDictionary<Key, Value> or a NameValueCollection can be configured in Xml by the following syntax. Say you have a class that needs a Dictionary of properties:</p> Modified: trunk/Source/HTML/AutoMocker.htm =================================================================== --- trunk/Source/HTML/AutoMocker.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/AutoMocker.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -1,9 +1,12 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>Auto Mocking Container with StructureMap</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> - + Forthcoming... ETA: 1st Qtr 2009 </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/ConstructorAndSetterInjection.htm =================================================================== --- trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -5,6 +5,12 @@ <link rel="stylesheet" type="text/css" href="style.css" /> <script type="text/javascript" src="jquery-1.2.6.js"></script> <script type="text/javascript" src="structuremap.js"></script> + <style type="text/css"> + .style1 + { + font-weight: normal; + } + </style> </head> <body> @@ -132,13 +138,82 @@ </div> <!--EndFragment--> <h4>Overriding the Constructor in the Registry DSL</h4> - <p>TODO</p> + <p>StructureMap has always allowed you to override the constructor choice with an + attribute, but increasingly, many people are unwilling to use attributes in + their code for infrastructure concerns. Other times you may want to + override the constructor choice of a class that you don't control. Either + way, it would be useful to select the constructor function used by StructureMap + to build a concrete code in the Registry DSL. The syntax to do just that + is shown below:</p> + <p>Let's say that you have this class (from the unit tests):</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassWithTwoConstructors\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 int\cf0 _age;\par ?? \cf3 private\cf0 \cf3 string\cf0 _name;\par ??\par ?? \cf3 public\cf0 ClassWithTwoConstructors(\cf3 int\cf0 age, \cf3 string\cf0 name)\par ?? \{\par ?? \cf4 Assert\cf0 .Fail(\cf5 "Should not be called"\cf0 );\par ??\par ?? _age = age;\par ?? _name = name;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 bool\cf0 WasConstructedWithNarrowCtor = \cf3 false\cf0 ;\par ?? \cf3 public\cf0 ClassWithTwoConstructors(\cf3 int\cf0 age)\par ?? \{\par ?? _age = age;\par ?? WasConstructedWithNarrowCtor = \cf3 true\cf0 ;\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">ClassWithTwoConstructors</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ClassWithTwoConstructors(<span style="color: blue;">int</span> age, + <span style="color: blue;">string</span> name)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ClassWithTwoConstructors(<span style="color: blue;">int</span> age)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>By default, StructureMap would choose the "greediest" constructor. In this + case, it would be the constructor that takes in "age" and "name." To force + StructureMap into using the other constructor, use the SelectConstructor() + method on the Registry:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SelectConstructor<\cf4 ClassWithTwoConstructors\cf0 >(()=>\cf3 new\cf0 \cf4 ClassWithTwoConstructors\cf0 (0));\par ?? x.ForConcreteType<\cf4 ClassWithTwoConstructors\cf0 >().Configure\par ?? .WithCtorArg(\cf5 "age"\cf0 ).EqualTo(34);\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SelectConstructor<<span style="color: #2b91af;">ClassWithTwoConstructors</span>>(()=><span + style="color: blue;">new</span> <span style="color: #2b91af;"> + ClassWithTwoConstructors</span>(0));</p> + <p style="margin: 0px;"> + + x.ForConcreteType<<span style="color: #2b91af;">ClassWithTwoConstructors</span>>().Configure</p> + <p style="margin: 0px;"> + + .WithCtorArg(<span style="color: #a31515;">"age"</span>).EqualTo(34);</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p>The argument to the SelectConstructor is an Expression of type + Expression<Func<T>> where T is the concrete class. StructureMap parses the + Expression to find the constructor function in the Expression object.</p> <hr /> - <h2>Using Setter Injection</h2> + <h2 class="style1">Using Setter Injection</h2> <p>Setter injection is a pattern of "injecting" dependencies via public properties. Setter Injection with StructureMap is somewhat a second class citizen, but this is partially by design. My strong recommendation is to use @@ -478,11 +553,124 @@ --> <!--EndFragment--> <hr /> - <h4><a name="SetterPolicies"></a>Creating Policies for Setter Injection</h4><p>TODO</p> - <hr /> <h4>Applying Setter Injection to an Existing Object (BuildUp)</h4> - <p>TODO</p> + <p>asdf</p> + <hr /> + <h4><a name="SetterPolicies"></a>Creating Policies for Setter Injection</h4> + <p>New in StructureMap 2.5.2+ is the ability to create setter injection policies. + What this means is that you create conventions to define which public setter + properties will be mandatory in the construction of objects. </p> + <h4>Specify a Setter Policy by Property Name</h4> + <p>The sample below will make all public setter properties mandatory where the + property name is suffixed by "Service." The call to NameMatches() takes in + a Predicate<string> that is a test against the property name.</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.NameMatches(name => name.EndsWith(\cf5 "Name"\cf0 ));\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.NameMatches(name => name.EndsWith(<span style="color: #a31515;">"Service"</span>));</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<hr /> + <h4>Specify a Setter Policy by Property Type</h4> + <p> </p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.OfType<\cf3 string\cf0 >();\par ?? policy.OfType<\cf4 IGateway\cf0 >();\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.OfType<<span style="color: blue;">string</span>>();</p> + <p style="margin: 0px;"> + + policy.OfType<<span style="color: #2b91af;">IGateway</span>>();</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p> </p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespaceContainingType<\cf4 ClassWithNamedProperties\cf0 >();\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.WithAnyTypeFromNamespaceContainingType<<span style="color: #2b91af;">ClassWithNamedProperties</span>>();</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p> </p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespace(\cf5 "StructureMap.Testing.Widget3"\cf0 );\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.WithAnyTypeFromNamespace(<span style="color: #a31515;">"StructureMap.Testing.Widget3"</span>);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p> </p> + <p> </p> <hr /> Modified: trunk/Source/HTML/Diagnostics.htm =================================================================== --- trunk/Source/HTML/Diagnostics.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/Diagnostics.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -2,8 +2,13 @@ <html> <head> <title>Diagnostics</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> + <p>More information coming, ETA: 1st Qtr 2009</p> + <h2>What do I Have?</h2> <p>text</p> <hr /> Modified: trunk/Source/HTML/HTML.csproj =================================================================== --- trunk/Source/HTML/HTML.csproj 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/HTML.csproj 2009-01-08 13:28:57 UTC (rev 217) @@ -64,7 +64,6 @@ <Content Include="FeatureList.htm" /> <Content Include="HowDoesStructureMapWork.htm" /> <Content Include="InversionOfControl.htm" /> - <Content Include="ModularConfiguration.htm" /> <Content Include="Profiles.htm" /> <Content Include="Scoping.htm" /> <Content Include="UsingAttributes.htm" /> Modified: trunk/Source/HTML/HowDoesStructureMapWork.htm =================================================================== --- trunk/Source/HTML/HowDoesStructureMapWork.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/HowDoesStructureMapWork.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -1,9 +1,12 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>How does StructureMap Work?</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> - + More information coming 1st Qtr 2009 </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/Interception.htm =================================================================== --- trunk/Source/HTML/Interception.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/Interception.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -7,19 +7,639 @@ <script type="text/javascript" src="structuremap.js"></script> </head> <body> - <p>Introduction</p> + <p>StructureMap 2.5+ added the ability to postprocess or even intercept and replace + the objects being created. While StructureMap will never include its own + Aspect Oriented Programming model (the world does not need a new one), the + interception techniques shown below could be used to apply runtime AOP from + existing AOP tools like the Policy Injection Application Block from Microsoft.</p> + <p>In general, interception is specified in three ways:</p> + <ol> + <li>OnCreation() -- Registers an Action to run against the new object after creation</li> + <li>EnrichWith() -- Registers a Func that runs against the new object after creation + and gives you the option of returning a different object than the original + object</li> + <li>A custom class that implements the TypeInterceptor interface (the runtime model + behind all the interception techniques)</li> + </ol> - <h2>Title</h2> - <p>Content</p> + + <p> + </p> + + + <h2>Intercept a Single Instance</h2> + <p>You can specify interception for a single Instance. This interception could + be combined with other Interception policies, but users should be cautious about + this. </p> + <h4>Run an Action Against an Object</h4> + <p>Some classes may require some extra bootstrapping work before they are ready to + be used. While I recommend building classes in such a way that the new + objects are ready to function after calling the constructor function, not every + class you will encounter will follow this rule. For that reason, + StructureMap has the ability to register an Action<T> to run against a newly + created object before it is returned to the requesting code. You can + register that Action on an individual Instance:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 InterceptionRegistry\cf0 : \cf4 Registry\par ??\cf0 \{\par ?? \cf3 public\cf0 InterceptionRegistry()\par ?? \{\par ?? \cf5 // Perform an Action<T> upon the object of type T \par ??\cf0 \cf5 // just created before it is returned to the caller\par ??\cf0 ForRequestedType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation(x => x.Start());\par ?? \par ?? \cf5 // or...\par ??\par ??\cf0 \cf5 // You can also register an Action<IContext, T> to get access\par ??\cf0 \cf5 // to all the services and capabilities of the BuildSession\par ??\cf0 ForRequestedType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation((context, x) =>\par ?? \{\par ?? \cf3 var\cf0 connection = context.GetInstance<\cf4 IConnectionPoint\cf0 >();\par ?? x.Connect(connection);\par ?? \});\par ??\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">InterceptionRegistry</span> : + <span style="color: #2b91af;">Registry</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + InterceptionRegistry()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;"> + // Perform an Action<T> upon the object of type T </span> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // just created before it is returned to the caller</span></p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .OnCreation(x => x.Start());</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // or...</span></p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // You can also register an Action<IContext, T> to get access</span></p> + <p style="margin: 0px;"> + <span style="color: green;"> + // to all the services and capabilities of the BuildSession</span></p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .OnCreation((context, x) =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> connection = context.GetInstance<<span + style="color: #2b91af;">IConnectionPoint</span>>();</p> + <p style="margin: 0px;"> + + x.Connect(connection);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> + <h4>Wrap or Substitute the Returned Object</h4> + <p>Sometimes you may want to wrap the constructed object in some sort of Decorator + or apply runtime AOP to the new object. In this case, StructureMap will + allow you to substitute the constructed object for the new wrapped object -- + with the restriction that the object returned must be assignable to the + requested PluginType. Let's consider the case of using a + <a href="http://resharper.codebetter.com/blogs/jeremy.miller/archive/2005/09/02/131613.aspx"> + Decorator</a> pattern to add logging to an existing service:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 LoggingDecorator\cf0 : \cf4 IConnectionListener\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 IConnectionListener\cf0 _inner;\par ??\par ?? \cf3 public\cf0 LoggingDecorator(\cf4 IConnectionListener\cf0 inner)\par ?? \{\par ?? _inner = inner;\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">LoggingDecorator</span> : + <span style="color: #2b91af;">IConnectionListener</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">readonly</span> <span style="color: #2b91af;"> + IConnectionListener</span> _inner;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + LoggingDecorator(<span style="color: #2b91af;">IConnectionListener</span> inner)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _inner = inner;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>When you register an instance of IConnectionListener, you can specify that the + constructed object get wrapped with a decorator using the EnrichWith() syntax + like this:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red0\green128\blue0;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 InterceptionRegistry()\par ?? \{\par ?? \cf4 // Perform an Action<T> upon the object of type T \par ??\cf0 \cf4 // just created before it is returned to the caller\par ??\cf0 ForRequestedType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation(x => x.Start());\par ?? \par ?? \cf4 // or...\par ??\par ??\cf0 \cf4 // You can also register an Action<IContext, T> to get access\par ??\cf0 \cf4 // to all the services and capabilities of the BuildSession\par ??\cf0 ForRequestedType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation((context, x) =>\par ?? \{\par ?? \cf3 var\cf0 connection = context.GetInstance<\cf5 IConnectionPoint\cf0 >();\par ?? x.Connect(connection);\par ?? \});\par ??\par ??\par ?? ForRequestedType<\cf5 IConnectionListener\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .EnrichWith(x => \cf3 new\cf0 \cf5 LoggingDecorator\cf0 (x));\par ??\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + InterceptionRegistry()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .EnrichWith(x => <span style="color: blue;">new</span> + <span style="color: #2b91af;">LoggingDecorator</span>(x));</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>In the sample registration above, a call to + Container.GetInstance<IConnectionListener>() will result in a new + ClassThatNeedsSomeBootstrapping wrapped in a LoggingDecorator object:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 [\cf3 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 see_the_enrichment_with_a_decorator_in_action()\par ?? \{\par ?? \cf4 var\cf0 container = \cf4 new\cf0 \cf3 Container\cf0 (\cf4 new\cf0 \cf3 InterceptionRegistry\cf0 ());\par ?? container.GetInstance<\cf3 IConnectionListener\cf0 >()\par ?? .ShouldBeOfType<\cf3 LoggingDecorator\cf0 >()\par ?? .Inner.ShouldBeOfType<\cf3 ClassThatNeedsSomeBootstrapping\cf0 >();\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">Test</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">void</span> + see_the_enrichment_with_a_decorator_in_action()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(<span style="color: blue;">new</span> + <span style="color: #2b91af;">InterceptionRegistry</span>());</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">IConnectionListener</span>>()</p> + <p style="margin: 0px;"> + + .ShouldBeOfType<<span style="color: #2b91af;">LoggingDecorator</span>>()</p> + <p style="margin: 0px;"> + + .Inner.ShouldBeOfType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>();</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>There is also an overload of EnrichWith() that takes in the IContext object:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 ForRequestedType<\cf3 IConnectionListener\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf3 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .EnrichWith((context, x) =>\par ?? \{\par ?? \cf4 var\cf0 connection = context.GetInstance<\cf3 IConnectionPoint\cf0 >();\par ?? x.Connect(connection);\par ??\par ?? \cf4 return\cf0 \cf4 new\cf0 \cf3 LoggingDecorator\cf0 (x);\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .EnrichWith((context, x) =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> connection = context.GetInstance<<span + style="color: #2b91af;">IConnectionPoint</span>>();</p> + <p style="margin: 0px;"> + + x.Connect(connection);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: blue;">return</span> <span style="color: blue;">new</span> + <span style="color: #2b91af;">LoggingDecorator</span>(x);</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p>See <a href="UsingSessionContext.htm">Using the Session Context</a> for more + information on using the IContext.</p> + <hr /> + <h4>With a Custom Interceptor</h4> + <p>To write a custom Interceptor for a single Instance, create a new class that + implements the InstaneInterceptor interface:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 InstanceInterceptor\par ??\cf0 \{\par ?? \cf3 object\cf0 Process(\cf3 object\cf0 target, \cf4 IContext\cf0 context);\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">interface</span> + <span style="color: #2b91af;">InstanceInterceptor</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">object</span> Process(<span + style="color: blue;">object</span> target, <span style="color: #2b91af;"> + IContext</span> context);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p> with a class like this:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 CustomInterceptor\cf0 : \cf4 InstanceInterceptor\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf3 object\cf0 Process(\cf3 object\cf0 target, \cf4 IContext\cf0 context)\par ?? \{\par ?? \cf5 // manipulate the target object and return a wrapped version\par ??\cf0 \cf3 return\cf0 wrapTarget(target);\par ?? \}\par ??\par ?? \cf3 private\cf0 \cf3 object\cf0 wrapTarget(\cf3 object\cf0 target)\par ?? \{\par ?? \cf3 throw\cf0 \cf3 new\cf0 \cf4 NotImplementedException\cf0 ();\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">CustomInterceptor</span> : + <span style="color: #2b91af;">InstanceInterceptor</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">object</span> Process(<span style="color: blue;">object</span> + target, <span style="color: #2b91af;">IContext</span> context)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;"> + // manipulate the target object and return a wrapped version</span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> wrapTarget(target);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">object</span> wrapTarget(<span style="color: blue;">object</span> + target)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;"> + NotImplementedException</span>();</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Then, register the a new object instance of the CustomerInterceptor:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 ForRequestedType<\cf3 IConnectionListener\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf3 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .InterceptWith(\cf4 new\cf0 \cf3 CustomInterceptor\cf0 ());} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .InterceptWith(<span style="color: blue;">new</span> + <span style="color: #2b91af;">CustomInterceptor</span>());</p> + </div> <hr /> + + + + <h2>Apply Interception to all Instances of a PluginType</h2> + <p>The same OnCreation(), EnrichWith(), and InterceptWith() methods can be applied + to all Instances of a given PluginType off of the ForRequestedType() or + BuildInstancesOf() methods of the <a href="RegistryDSL.htm">Registry DSL</a>:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 \cf3 // Place the Interception at the PluginType level\par ??\cf0 ForRequestedType<\cf4 IConnectionListener\cf0 >()\par ?? .OnCreation(x => x.StartConnection()) \cf3 // OnCreation\par ??\cf0 .EnrichWith(x => \cf5 new\cf0 \cf4 LoggingDecorator\cf0 (x)) \cf3 // Enrich\par ??\cf0 .InterceptWith(\cf5 new\cf0 \cf4 CustomInterceptor\cf0 ()) \cf3 // Custom Interceptor\par ??\par ??\par ??\cf0 .TheDefaultIsConcreteType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >();} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Place the Interception at the PluginType level</span></p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>()</p> + <p style="margin: 0px;"> + + .OnCreation(x => x.StartConnection()) + <span style="color: green;">// OnCreation</span></p> + <p style="margin: 0px;"> + + .EnrichWith(x => <span style="color: blue;">new</span> + <span style="color: #2b91af;">LoggingDecorator</span>(x)) + <span style="color: green;">// Enrich</span></p> + <p style="margin: 0px;"> + + .InterceptWith(<span style="color: blue;">new</span> + <span style="color: #2b91af;">CustomInterceptor</span>()) + <span style="color: green;">// Custom Interceptor</span></p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + .TheDefaultIsConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>();</p> + </div> +<!--EndFragment--> +<p>Note that these methods can be used in combination with each other and even + multiple times for the same type. All additional calls are additive. + Use with caution!</p> + <hr /> - <h2>Title</h2> - <p>Content</p> + + <h2>Apply Interception to all Types Matching a Criteria</h2> + <p>If an interception policy is simple, you can just register the interception + policy with the IfTypeMatches( Predicate<Type> ).InterceptWith( + Lambda ) syntax:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 registry.IfTypeMatches(type => type.Equals(\cf3 typeof\cf0 (\cf4 BlueSomething\cf0 )))\par ?? .InterceptWith(rawInstance => \cf3 new\cf0 \cf4 WrappedSomething\cf0 ((\cf4 IAnInterfaceOfSomeSort\cf0 ) rawInstance));} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + registry.IfTypeMatches(type + => type.Equals(<span style="color: blue;">typeof</span> (<span + style="color: #2b91af;">BlueSomething</span>)))</p> + <p style="margin: 0px;"> + + .InterceptWith(rawInstance => <span style="color: blue;">new</span> + <span style="color: #2b91af;">WrappedSomething</span>((<span + style="color: #2b91af;">IAnInterfaceOfSomeSort</span>) rawInstance));</p> + </div> +<!--EndFragment--> +<p>Please note that when StructureMap encounters a new concrete type for the first + time, it searches for all TypeInterceptors that match that the concrete type, + and caches these TypeInterceptors against the concrete type for future usage. + The long and short of this is that any filter on the type is only going to be + evaluated once.</p> <hr /> - <h2>Title</h2> - <p>Content</p> + <h2>Creating a Custom Type Interceptor</h2> + <p>Sooner or later the Fluent Interface registration of TypeInterceptors will not be + adequate. In that case, you can create a custom class that implements the + TypeInterceptor interface:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 ///\cf4 \cf3 <summary>\par ??\cf0 \cf3 ///\cf4 A TypeInterceptor that is only applied if the MatchesType()\par ??\cf0 \cf3 ///\cf4 method is true for a given Type\par ??\cf0 \cf3 ///\cf4 \cf3 </summary>\par ??\cf0 \cf5 public\cf0 \cf5 interface\cf0 \cf6 TypeInterceptor\cf0 : \cf6 InstanceInterceptor\par ??\cf0 \{\par ?? \cf3 ///\cf4 \cf3 <summary>\par ??\cf0 \cf3 ///\cf4 Does this TypeInterceptor apply to the given type?\par ??\cf0 \cf3 ///\cf4 \cf3 </summary>\par ??\cf0 \cf3 ///\cf4 \cf3 <param name="type"></param>\par ??\cf0 \cf3 ///\cf4 \cf3 <returns></returns>\par ??\cf0 \cf5 bool\cf0 MatchesType(\cf6 Type\cf0 type);\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> </span> + <span style="color: gray;"><summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> A + TypeInterceptor that is only applied if the MatchesType()</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> method is + true for a given Type</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> </span> + <span style="color: gray;"></summary></span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">interface</span> + <span style="color: #2b91af;">TypeInterceptor</span> : + <span style="color: #2b91af;">InstanceInterceptor</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> Does this TypeInterceptor apply to the given type?</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"></summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><param + name="type"></param></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><returns></returns></span></p> + <p style="margin: 0px;"> + <span style="color: blue;">bool</span> MatchesType(<span + style="color: #2b91af;">Type</span> type);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Registered TypeInterceptor objects are applied against any object created by + StructureMap if the type of the new object meets the MatchesType() method of + TypeInterceptor. You can happil... [truncated message content] |