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] |