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