From: <jer...@us...> - 2009-01-04 02:55:46
|
Revision: 215 http://structuremap.svn.sourceforge.net/structuremap/?rev=215&view=rev Author: jeremydmiller Date: 2009-01-04 02:55:42 +0000 (Sun, 04 Jan 2009) Log Message: ----------- More documentation and examples, some new convenience methods in TypeExtensions, a convenience FI for fetching generic types, IContainer is always injected into the Container Modified Paths: -------------- trunk/Source/CommonAssemblyInfo.cs trunk/Source/HTML/AutoWiring.htm trunk/Source/HTML/Default.htm trunk/Source/HTML/FeatureList.htm trunk/Source/HTML/Generics.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/Menu.htm trunk/Source/HTML/ScanningAssemblies.htm trunk/Source/HTML/Scoping.htm trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/FindAllTypesFilter.cs trunk/Source/StructureMap/IContainer.cs trunk/Source/StructureMap/ObjectFactory.cs trunk/Source/StructureMap/StructureMapException.resx trunk/Source/StructureMap/TypeExtensions.cs trunk/Source/StructureMap.Testing/AutoWiringExamples.cs trunk/Source/StructureMap.Testing/Graph/AssemblyScannerTester.cs trunk/Source/StructureMap.Testing/Graph/DefaultConventionScanningTester.cs trunk/Source/StructureMap.Testing/ModelQueryTester.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj trunk/Source/StructureMap.Testing/TestData/DefaultInstance.xml trunk/Source/StructureMap.Testing/TestData/ScopeInFamily.xml Added Paths: ----------- trunk/Source/StructureMap.Testing/Pipeline/ContainerIsInTheContainerTester.cs trunk/Source/StructureMap.Testing/Pipeline/GenericsHelperExpressionTester.cs trunk/Source/StructureMap.Testing/TypeExtensionsTester.cs Removed Paths: ------------- trunk/Source/HTML/SmartInstance.htm Modified: trunk/Source/CommonAssemblyInfo.cs =================================================================== --- trunk/Source/CommonAssemblyInfo.cs 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/CommonAssemblyInfo.cs 2009-01-04 02:55:42 UTC (rev 215) @@ -13,11 +13,11 @@ //------------------------------------------------------------------------------ [assembly: ComVisibleAttribute(false)] -[assembly: AssemblyVersionAttribute("2.5.1.0000")] +[assembly: AssemblyVersionAttribute("2.5.2.0000")] [assembly: AssemblyCopyrightAttribute("Copyright (c) 2003-2008, Jeremy D. Miller")] [assembly: AssemblyProductAttribute("StructureMap")] [assembly: AssemblyCompanyAttribute("")] [assembly: AssemblyConfigurationAttribute("release")] -[assembly: AssemblyInformationalVersionAttribute("2.5.1.0000")] -[assembly: AssemblyFileVersionAttribute("2.5.1.0000")] +[assembly: AssemblyInformationalVersionAttribute("2.5.2.0000")] +[assembly: AssemblyFileVersionAttribute("2.5.2.0000")] Modified: trunk/Source/HTML/AutoWiring.htm =================================================================== --- trunk/Source/HTML/AutoWiring.htm 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/HTML/AutoWiring.htm 2009-01-04 02:55:42 UTC (rev 215) @@ -82,16 +82,15 @@ <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"> + 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:<div class="code-sample"><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> @@ -216,10 +215,223 @@ overriden.</p> <hr /> <h4>Object Identity within a Single Request</h4> - <p>TODO</p> + <p>Within a single object request, StructureMap will only create a single object for + a single Instance configuration. What that means in effect is that if two + or more objects in a single request need the same dependency, those two objects + will get the exact same instance of that dependency. Let's immediately + jump into code to demonstrate this.</p> + <p>This auto wiring policy was intended for objects that need to be shared by lots + of other objects. A common example of this is some sort of DataContext + class:</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;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 DataContext\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 Guid\cf0 _id = \cf4 Guid\cf0 .NewGuid();\par ??\par ?? \cf3 public\cf0 \cf3 override\cf0 \cf3 string\cf0 ToString()\par ?? \{\par ?? \cf3 return\cf0 \cf3 string\cf0 .Format(\cf5 "Id: \{0\}"\cf0 , _id);\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;"> + DataContext</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + private</span> <span style="color: #2b91af;">Guid</span> _id = + <span style="color: #2b91af;">Guid</span>.NewGuid();</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;">"Id: {0}"</span>, _id);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Now, let's say that I have a hierarchy of classes that all need to work on a + DataContext:</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;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 Class1\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 DataContext\cf0 _context;\par ??\par ?? \cf3 public\cf0 Class1(\cf4 DataContext\cf0 context)\par ?? \{\par ?? _context = context;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 override\cf0 \cf3 string\cf0 ToString()\par ?? \{\par ?? \cf3 return\cf0 \cf3 string\cf0 .Format(\cf5 "Class1 has Context: \{0\}"\cf0 , _context);\par ?? \}\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Class2\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 Class1\cf0 _class1;\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 DataContext\cf0 _context;\par ??\par ?? \cf3 public\cf0 Class2(\cf4 Class1\cf0 class1, \cf4 DataContext\cf0 context)\par ?? \{\par ?? _class1 = class1;\par ?? _context = context;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 override\cf0 \cf3 string\cf0 ToString()\par ?? \{\par ?? \cf3 return\cf0 \cf3 string\cf0 .Format(\cf5 "Class2 has Context: \{0\}\\n\{1\}"\cf0 , _context, _class1);\par ?? \}\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Class3\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 Class2\cf0 _class2;\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 DataContext\cf0 _context;\par ??\par ?? \cf3 public\cf0 Class3(\cf4 Class2\cf0 class2, \cf4 DataContext\cf0 context)\par ?? \{\par ?? _class2 = class2;\par ?? _context = context;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 override\cf0 \cf3 string\cf0 ToString()\par ?? \{\par ?? \cf3 return\cf0 \cf3 string\cf0 .Format(\cf5 "Class3 has Context: \{0\}\\n\{1\}"\cf0 , _context, _class2);\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;">Class1</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + public</span> Class1(<span style="color: #2b91af;">DataContext</span> context){}</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;">"Class1 has Context: {0}"</span>, _context);</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;">Class2</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + public</span> Class2(<span style="color: #2b91af;">Class1</span> class1, + <span style="color: #2b91af;">DataContext</span> context) {}</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;">"Class2 has Context: {0}\n{1}"</span>, _context, + _class1);</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;">Class3</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">public</span> Class3(<span style="color: #2b91af;">Class2</span> + class2, <span style="color: #2b91af;">DataContext</span> context) {}</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;">"Class3 has Context: {0}\n{1}"</span>, _context, + _class2);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>When you request an object of Class3 with a call to + Container.GetInstance<Class3>() like this:</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 demonstrate_session_identity()\par ?? \{\par ?? \cf4 var\cf0 class3 = container.GetInstance<\cf3 Class3\cf0 >();\par ?? \cf3 Debug\cf0 .WriteLine(class3);\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> demonstrate_session_identity()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> class3 = container.GetInstance<<span style="color: #2b91af;">Class3</span>>();</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(class3);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>The output is:</p> +<pre> +Class3 has Context: Id: 3abe0330-e94f-48a3-b8c3-56d278eea07f +Class2 has Context: Id: 3abe0330-e94f-48a3-b8c3-56d278eea07f +Class1 has Context: Id: 3abe0330-e94f-48a3-b8c3-56d278eea07f +</pre> + <p>In the sample above, when we write out the Class3, Class2, and Class1 objects to Debug.WriteLine, we find that each of these objects have a reference to the same DataContext. If we were to run this test again, the output might be:</p> + <pre> +Class3 has Context: Id: 109329ce-4058-4a35-9fd1-46d47c1e69e7 +Class2 has Context: Id: 109329ce-4058-4a35-9fd1-46d47c1e69e7 +Class1 has Context: Id: 109329ce-4058-4a35-9fd1-46d47c1e69e7 + </pre> + <p>We see the exact same behavior, but it was a different object instance of DataContext for the new object graph.</p> + <p>This behavior also applies to objects passed in to the Container as an explicit argument:</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;\red163\green21\blue21;}??\fs20 [\cf3 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 demonstrate_session_identity_with_explicit_argument()\par ?? \{\par ?? \cf3 DataContext\cf0 context = \cf4 new\cf0 \cf3 DataContext\cf0 ();\par ?? \cf3 Debug\cf0 .WriteLine(\cf5 "The context being passed in is "\cf0 + context);\par ??\par ?? \cf4 var\cf0 class3 = container.With(context).GetInstance<\cf3 Class3\cf0 >();\par ?? \cf3 Debug\cf0 .WriteLine(class3);\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> + demonstrate_session_identity_with_explicit_argument()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + DataContext</span> context = <span style="color: blue;">new</span> + <span style="color: #2b91af;">DataContext</span>();</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"The context being passed + in is "</span> + context);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> class3 = container.With(context).GetInstance<<span + style="color: #2b91af;">Class3</span>>();</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(class3);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>The output of this unit test is:</p> + <pre> +The context being passed in is Id: 87ddccfd-a441-41fd-a86d-3f32987496ba +Class3 has Context: Id: 87ddccfd-a441-41fd-a86d-3f32987496ba +Class2 has Context: Id: 87ddccfd-a441-41fd-a86d-3f32987496ba +Class1 has Context: Id: 87ddccfd-a441-41fd-a86d-3f32987496ba + </pre> + <p>The point of the sample above is just to show that the object instance of DataContext passed into the Container is used to create the Class3, Class2, and Class1 objects.</p> <hr /> <h4>Injecting Arrays of Services</h4> - <p>TODO</p> + <p>StructureMap has always supported Dependency Injection of arrays of dependency + objects. New in StructureMap 2.5+ is a policy that if any array of + dependencies is not explicitly specified, StructureMap will inject all possible + instances of that dependency type. The sample below illustrates this auto + wiring policy. I have a class called "ClassThatUsesValidators" that needs + an array of IValidator objects. Below, I've configured two different + Instances of ClassThatUsesValidator, one that explicitly configures its children + IValidator and another Instance that is just going to let auto wiring inject the + IValidator's.</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 ?? \}} --> @@ -454,8 +666,18 @@ }</p> </div> <!--EndFragment--> -<p> </p> - <p> </p> +<p>The output of what_are_the_validators() is:</p> +<pre> +With Auto Wiring +Name: Red +Name: Blue +Name: Purple +Name: Green +================================= +With Explicit Configuration +Name: Red +Name: Green +</pre> <hr /> </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/Default.htm =================================================================== --- trunk/Source/HTML/Default.htm 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/HTML/Default.htm 2009-01-04 02:55:42 UTC (rev 215) @@ -90,53 +90,6 @@ <p> </p> <p> </p> - <h3>Feature List</h3> - <UL> - <li> - Creates objects using the <a href="http://picocontainer.codehaus.org/Constructor+Injection"> - Constructor Injection pattern</a> </li> - <LI> - Optionally, attach dependencies and other properties through Setter Injection - (v0.90) - <LI> - Runtime linking of object dependencies - <LI> - Configurable object <a href="Scoping.htm">lifecycle - scoping</a> (v1.0)<LI> - Optional support for an - <a href="SingletonInjection.htm">Injected Singleton</a> (v0.90) - <LI> - Generalized support for the - <a href="Concepts.htm#Plugin">Plugin</a> pattern using (almost) any type of class or - interface - <LI> - Configurable either implicitly through - <a href="Attributes.htm">custom attributes</a> or explicitly through - XML configuration - <LI> - Optional log4net integration - <LI> - <EM>Mock Injection</EM> using built in support for <a href="http://sourceforge.net/projects/nmock/"> - NMock</a> - <LI> - Runtime injection of a static mock or stub (v0.90) - <LI> - Machine level overrides of default configuration - <LI> - Profile overrides of default configuration -- i.e. "Remote" vs "Local" vs - "Stubbed" dependency profiles - <LI> - NAnt tasks for diagnostic verification of configuration and deployment - utilities for easier continuous integration (v0.90) - <LI> - Command line utility for troubleshooting runtime configuration issues - (v0.90) - <LI> - Diagnostic WinForms tool for exploring and - troubleshooting configuration (v1.0)<LI> - Uses Reflection.Emit namespace classes to create IL code on the fly for - performance superior to Reflection based approaches</LI> - </UL> </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/FeatureList.htm =================================================================== --- trunk/Source/HTML/FeatureList.htm 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/HTML/FeatureList.htm 2009-01-04 02:55:42 UTC (rev 215) @@ -8,5 +8,59 @@ </head> <body> + <p> + StructureMap includes all of the basic capabilities of an IoC tool, plus much, + much more:</p> + <UL> + <li> + Creates objects using the <a href="http://picocontainer.codehaus.org/Constructor+Injection"> + Constructor Injection pattern</a> + <UL> + <li>Constructor function selection can be overriden programmatically or with an + attribute</li> + </UL> + </li> + <LI> + Optionally, attach dependencies and other properties through Setter Injection. + Properties can be configured to be mandatory dependencies or optional + dependencies.<UL> + <LI>Convention based setter injection policies</UL> + <LI> + Runtime linking of object dependencies + with auto wiring<LI> + "Build Up" using setter injection to attach dependencies to an externally + constructed object<LI> + Can be configured to create or resolve objects by:<UL> + <LI>Calling constructor functions<LI>Lambda expressions<LI>Cloning a prototype + object<LI>Loading a UserControl<LI>UUsing an externally created object<LI> + Conditional Construction of objects<LI>Custom method of construction objects</UL> + <LI>Object graphs can be configured inline to override auto wiringLI>Contextual + construction of objects<LI>"Missing Instance" handling<LI>Passing + explicit arguments into the Container<LI> + Configurable object <a href="Scoping.htm">lifecycle + scoping</a> (singleton, transient, HttpContext, ThreadLocal)<LI> + Auto registration with pluggable type convention rules<LI>Generalized support for the + <a href="Concepts.htm#Plugin">Plugin</a> pattern using (almost) any type of class or + interface + <LI>Configurable either implicitly through + a programmatic DSL, <a href="UsingAttributes.htm">custom attributes</a>, or explicitly through + XML configuration + <LI>Very modular configuration options. Mix and match any form of + configuration at one time.<LI>Configuration can be added at runtime<LI>Supports type registration of open generic types<LI>Interception capabilities to + apply runtime AOP or decorators<LI>Extensible + object creation<LI><EM>Mock Injection</EM> with Containers + <LI>Runtime injection of a static mock or stub<LI>An Auto Mocking Container that + can be used with any .Net mocking framework. Rhino Mocks "Classic", Rhino + Mocks AAA, and Moq are supported out of the box<LI>Machine level overrides of default configuration + <LI>Profile overrides of default configuration -- i.e. "Remote" vs "Local" vs + "Stubbed" dependency profiles + <LI>Command line utility for troubleshooting runtime configuration issues<UL> + <LI>Diagnostic querying of the Container configuration (Linq to StructureMap, sort + of)<LI>"Assert" configuration + is valid<LI>Environment Test Support<LI>Custom Debugger</UL> + <LI>Uses Reflection.Emit namespace classes to create IL code on the fly for + performance superior to Reflection based approaches</LI> + </UL> + </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/Generics.htm =================================================================== --- trunk/Source/HTML/Generics.htm 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/HTML/Generics.htm 2009-01-04 02:55:42 UTC (rev 215) @@ -2,8 +2,342 @@ <html> <head> <title>Using Open Generic Types</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>StructureMap directly supports open generic types[LINK]*. This is most + easily explained by a demonstration. I'm currently working on an MVC + application that uses a lot of semi-RESTful services that return Json. + These Json service methods are implemented by methods on a Controller class that + by convention, all return a single object:</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 class\cf0 \cf4 FindAddressController\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 Address\cf0 FindAddress(\cf3 long\cf0 id)\par ?? \{\par ?? \cf3 return\cf0 \cf3 null\cf0 ;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf4 Continuation\cf0 WhatShouldTheUserDoNext()\par ?? \{\par ?? \cf3 return\cf0 \cf3 null\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;">FindAddressController</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: #2b91af;">Address</span> FindAddress(<span + style="color: blue;">long</span> id){}</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: #2b91af;">Continuation</span> WhatShouldTheUserDoNext() {}</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>When these methods are executed in our MVC applications, the output objects + (Address or Continuation) are serialized to Json by other code and sent down to + the client. It's worked out well, but there's one little wrinkle from the + code above that we stumbled upon:</p> + <ol> + <li>Continuation is basically a dumb Data Transfer Object[LINK] class that's + perfectly suited for being Json serialized and consumed by JavaScript on the + client</li> + <li>Address is an Entity[LINK] class in our Domain Model, and very poorly suited to + Json serialization. Besides the fact that we probably wouldn't want the + shape of our Domain Model classes to be coupled to the client JavaScript, the + Entity classes are jagged, have lots of lazy loaded members, and contain a fair + amount of data we may not want to send down to the client (plus the Json + serialization does poorly with bidirectional dependencies). Direct Json + serialization is out.</li> + </ol> + <p>What we needed to do was convert the Entity objects (and any other object that + wasn't suited to Json serialization and client usage) into a UI-friendly Data + Transfer Object. Other objects like Continuation that were already Json + friendly, we could just use as is. The solution we came up with was the + "ObjectFlattener:"</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;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 ObjectFlattener\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 IContainer\cf0 _container;\par ??\par ?? \cf5 // You can inject the IContainer itself into an object by the way...\par ??\cf0 \cf3 public\cf0 ObjectFlattener(\cf4 IContainer\cf0 container)\par ?? \{\par ?? _container = container;\par ?? \}\par ??\par ?? \cf5 // This method can "flatten" any object\par ??\cf0 \cf3 public\cf0 \cf3 object\cf0 Flatten(\cf3 object\cf0 input)\par ?? \{\par ?? \cf3 var\cf0 flattener = _container.ForGenericType(\cf3 typeof\cf0 (\cf4 IFlattener\cf0 <>))\par ?? .WithParameters(input.GetType())\par ?? .GetInstanceAs<\cf4 IFlattener\cf0 >();\par ??\par ?? \cf3 return\cf0 flattener.ToDto(input);\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;">ObjectFlattener</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;"> + IContainer</span> _container;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;">// You can inject the + IContainer itself into an object by the way...</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ObjectFlattener(<span style="color: #2b91af;">IContainer</span> container)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _container = container;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;">// This method can + "flatten" any object</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">object</span> Flatten(<span style="color: blue;">object</span> + input)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> flattener = _container.ForGenericType(<span style="color: blue;">typeof</span> + (<span style="color: #2b91af;">IFlattener</span><>))</p> + <p style="margin: 0px;"> + + .WithParameters(input.GetType())</p> + <p style="margin: 0px;"> + + .GetInstanceAs<<span style="color: #2b91af;">IFlattener</span>>();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> flattener.ToDto(input);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>The ObjectFlattener can take in any object, select a strategy for "flattening" + that object into something Json friendly, and return the Json friendly object. + ObjectFlattener is dirt simple. It simply finds the correct IFlattener for + the object type passed into the Flatten(object) method:</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 IFlattener\par ??\cf0 \{\par ?? \cf3 object\cf0 ToDto(\cf3 object\cf0 input);\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;">IFlattener</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">object</span> ToDto(<span + style="color: blue;">object</span> input);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>ObjectFlattener needs to find the corrent IFlattener for the object Type passed + in, so it's really looking for the type:</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 IFlattener\cf0 <T> : \cf4 IFlattener\par ??\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;">interface</span> + <span style="color: #2b91af;">IFlattener</span><T> : + <span style="color: #2b91af;">IFlattener</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>where "T" is the type of object passed into the ToDto(object) method. When + an Address object is passed into ToDto(), ObjectFlattener finds the default + instance of IFlattener<Address>. The + "ForGenericType().WithParameters().GetInstanceAs<T>()" syntax is a helper + expression to create and request a closed generic type from an open generic + template and the appropriate generic parameter types.</p> + <p>Now, we said that many objects like Continuation in our system are DTO's to begin + with and don't need to be "flattened." For those objects, we use a "Nullo" + implementation of IFlattener that just returns the object passed in without any + transformation:</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 class\cf0 \cf4 PassthroughFlattener\cf0 <T> : \cf4 IFlattener\cf0 <T>\par ?? \{\par ?? \cf3 public\cf0 \cf3 object\cf0 ToDto(\cf3 object\cf0 input)\par ?? \{\par ?? \cf3 return\cf0 input;\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;">PassthroughFlattener</span><T> : + <span style="color: #2b91af;">IFlattener</span><T></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">object</span> ToDto(<span style="color: blue;">object</span> + input)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> input;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>The Address class needs some transformation, so we'll create an AddressFlattener + class:</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;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 AddressFlattener\cf0 : \cf4 IFlattener\cf0 <\cf4 Address\cf0 >\par ?? \{\par ?? \cf3 public\cf0 \cf3 object\cf0 ToDto(\cf3 object\cf0 input)\par ?? \{\par ?? \cf3 var\cf0 dto = createDTO((\cf4 Address\cf0 ) input);\par ?? \cf3 return\cf0 dto;\par ?? \}\par ??\par ?? \cf3 private\cf0 \cf3 object\cf0 createDTO(\cf4 Address\cf0 input)\par ?? \{\par ?? \cf5 // creates the AddressDTO object from the \par ??\cf0 \cf5 // Address object passed in\par ??\cf0 \cf3 throw\cf0 \cf3 new\cf0 System.\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;">AddressFlattener</span> : + <span style="color: #2b91af;">IFlattener</span><<span style="color: #2b91af;">Address</span>></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">object</span> ToDto(<span style="color: blue;">object</span> + input)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> dto = createDTO((<span style="color: #2b91af;">Address</span>) + input);</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> dto;</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> createDTO(<span + style="color: #2b91af;">Address</span> input)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;"> + // creates the AddressDTO object from the </span> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // Address object passed in</span></p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Great, but now let's move on to registering these classes with a Container. + This unit test fixture from the code illustrates this very scenario:</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;\red0\green0\blue255;\red0\green128\blue0;}??\fs20 [\cf3 SetUp\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 SetUp()\par ?? \{\par ?? container = \cf4 new\cf0 \cf3 Container\cf0 (x =>\par ?? \{\par ?? \cf5 // Define the basic open type for IFlattener<>\par ??\cf0 x.ForRequestedType(\cf4 typeof\cf0 (\cf3 IFlattener\cf0 <>)).TheDefaultIsConcreteType(\cf4 typeof\cf0 (\cf3 PassthroughFlattener\cf0 <>));\par ?? \par ?? \cf5 // Explicitly Register a specific closed type for Address\par ??\cf0 x.ForRequestedType<\cf3 IFlattener\cf0 <\cf3 Address\cf0 >>().TheDefaultIsConcreteType<\cf3 AddressFlattener\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: #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;"> + + <span style="color: green;">// Define the basic open type for IFlattener<></span></p> + <p style="margin: 0px;"> + + x.ForRequestedType(<span style="color: blue;">typeof</span> (<span + style="color: #2b91af;">IFlattener</span><>)).TheDefaultIsConcreteType(<span + style="color: blue;">typeof</span> (<span style="color: #2b91af;">PassthroughFlattener</span><>));</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// Explicitly Register a specific closed type for + Address</span></p> + <p style="margin: 0px;"> + + x.ForRequestedType<<span style="color: #2b91af;">IFlattener</span><<span + style="color: #2b91af;">Address</span>>>().TheDefaultIsConcreteType<<span + style="color: #2b91af;">AddressFlattener</span>>();</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>In the code above we registered a specific concrete type for IFlattener<Address>, + and the open generic type PassthroughFlattener<T> for requests to IFlattener<T>. + When we request an instance of IFlattener<Address>, StructureMap behaves as + expected and returns a AddressFlattener object:</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;\red0\green0\blue255;}??\fs20 [\cf3 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 asking_for_a_closed_type_that_is_explicitly_registered_returns_the_explicitly_defined_type()\par ?? \{\par ?? container.GetInstance<\cf3 IFlattener\cf0 <\cf3 Address\cf0 >>()\par ?? .ShouldBeOfType<\cf3 AddressFlattener\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> + asking_for_a_closed_type_that_is_explicitly_registered_returns_the_explicitly_defined_type()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">IFlattener</span><<span style="color: #2b91af;">Address</span>>>()</p> + <p style="margin: 0px;"> + + .ShouldBeOfType<<span style="color: #2b91af;">AddressFlattener</span>>();</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Now, we'll ask for an instance of IFlattener<Continuation>. You'll notice + that we didn't explicitly register that specific type. When the Container + gets the request for IFlattener<Continuation>, it first looks to see if it + already knows how to build that specific type. In this case the Container + doesn't already know about IFlattener<Continuation>, but it does know about the + open type IFlattener<T> template, so it can use that configuration to create the + closed type IFlattener<Continuation>:</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;\red0\green0\blue255;}??\fs20 [\cf3 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 asking_for_a_closed_type_that_is_not_explicitly_registered_will_close_the_open_type_template()\par ?? \{\par ?? container.GetInstance<\cf3 IFlattener\cf0 <\cf3 Continuation\cf0 >>()\par ?? .ShouldBeOfType<\cf3 PassthroughFlattener\cf0 <\cf3 Continuation\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> + asking_for_a_closed_type_that_is_not_explicitly_registered_will_close_the_open_type_template()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">IFlattener</span><<span style="color: #2b91af;">Continuation</span>>>()</p> + <p style="margin: 0px;"> + + .ShouldBeOfType<<span style="color: #2b91af;">PassthroughFlattener</span><<span + style="color: #2b91af;">Continuation</span>>>();</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> + <p> + </p> + <p> + * Anytime I read one of those "look I'm so clever I can write my own IoC + container in 50 lines of code" blog posts, my immediate response is "oh yeah, + can you handle open generic types smart guy?"</p> + </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/HTML.csproj =================================================================== --- trunk/Source/HTML/HTML.csproj 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/HTML/HTML.csproj 2009-01-04 02:55:42 UTC (rev 215) @@ -65,7 +65,6 @@ <Content Include="ModularConfiguration.htm" /> <Content Include="Profiles.htm" /> <Content Include="Scoping.htm" /> - <Content Include="SmartInstance.htm" /> <Content Include="UsingAttributes.htm" /> <Content Include="AutoWiring.htm" /> <Content Include="ConfiguringStructureMap.htm" /> Modified: trunk/Source/HTML/Menu.htm =================================================================== --- trunk/Source/HTML/Menu.htm 2009-01-03 00:07:32 UTC (rev 214) +++ trunk/Source/HTML/Menu.htm 2009-01-04 02:55:42 UTC (rev 215) @@ -66,12 +66,13 @@ <li><a href="../../UsingTheContainerOutsideOfObjectFactory.htm">... [truncated message content] |