From: <jer...@us...> - 2009-01-11 22:43:15
|
Revision: 219 http://structuremap.svn.sourceforge.net/structuremap/?rev=219&view=rev Author: jeremydmiller Date: 2009-01-11 22:43:11 +0000 (Sun, 11 Jan 2009) Log Message: ----------- adding TryGet****** to IContext/BuildSession Modified Paths: -------------- trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/HTML/UsingSessionContext.htm trunk/Source/StructureMap/BuildSession.cs trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/PipelineGraph.cs trunk/Source/StructureMap.Testing/BuildSessionTester.cs trunk/Source/StructureMap.Testing/BuildUpIntegratedTester.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj Added Paths: ----------- trunk/Source/StructureMap.Testing/Examples/BuildUp.cs Modified: trunk/Source/HTML/ConstructorAndSetterInjection.htm =================================================================== --- trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-11 22:43:11 UTC (rev 219) @@ -61,7 +61,8 @@ <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;}??\fs20 \cf3 public\cf0 GreaterThanRule()\par ?? \{\par ?? \}\par ??\par ?? \cf3 public\cf0 GreaterThanRule(\cf3 string\cf0 Attribute, \cf3 int\cf0 Value)\par ?? \{\par ?? _Attribute = Attribute;\par ?? _Value = Value;\par ?? \}} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;" + class="code-sample"> <p style="margin: 0px;"> <span style="color: blue;">public</span> GreaterThanRule()</p> @@ -107,7 +108,8 @@ <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 [\cf3 DefaultConstructor\cf0 ]\par ?? \cf4 public\cf0 DataSession(\cf3 IDatabaseEngine\cf0 database)\par ?? : \cf4 this\cf0 (database,\par ?? \cf4 new\cf0 \cf3 CommandFactory\cf0 (database),\par ?? \cf4 new\cf0 \cf3 AutoCommitExecutionState\cf0 (database.GetConnection(), database.GetDataAdapter()),\par ?? \cf4 new\cf0 \cf3 TransactionalExecutionState\cf0 (database.GetConnection(), database.GetDataAdapter()))\par ?? \{\par ?? \}} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;" + class="code-sample"> <p style="margin: 0px;"> [<span style="color: #2b91af;">DefaultConstructor</span>]</p> <p style="margin: 0px;"> @@ -386,7 +388,7 @@ <span style="color: #2b91af;">Rule</span>[] Rules { <span style="color: blue;"> get</span>; <span style="color: blue;">set</span>; }</p> <p style="margin: 0px;"> -& }</p> + }</p> </div> <!--EndFragment--> <p>I can explicitly configure what gets injected into the "Rule" property for a @@ -555,8 +557,192 @@ <hr /> <h2>Applying Setter Injection to an Existing Object (BuildUp)</h2> - <p>asdf</p> - <hr /> + <p>Many times you simply cannot control when an object is going to be created + (ASP.Net WebForms), but you may still want to inject dependencies and even + primitive values into an already constructed object. To fill this gap, + StructureMap 2.5.2+ introduces the "BuildUp()" method on Container and + ObjectFactory. BuildUp() works by finding the default Instance for the + concrete type passed into the BuildUp() method (or create a new Instance if one + does not already exist), then applying any setters from that Instance + configuration. At this time, StructureMap does not apply interception + inside of BuildUp().</p> + <p>Let's say that we have a class called "BuildTarget1" like + this:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 BuildUpTarget1\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 IGateway\cf0 Gateway \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf4 IService\cf0 Service \{ \cf3 get\cf0 ; \cf3 set\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: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">BuildUpTarget1</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: #2b91af;">IGateway</span> Gateway { + <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> + }</div> +<p>In usage, we'd like to have the Gateway dependency injected into a new instance of the BuildTarget1 class when we call BuildUp():</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 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 create_a_setter_rule_and_see_it_applied_in_BuildUp_through_ObjectFactory()\par ?? \{\par ?? \cf4 var\cf0 theGateway = \cf4 new\cf0 \cf3 DefaultGateway\cf0 ();\par ?? \cf3 ObjectFactory\cf0 .Initialize(x =>\par ?? \{\par ?? x.IgnoreStructureMapConfig = \cf4 true\cf0 ;\par ?? x.ForRequestedType<\cf3 IGateway\cf0 >().TheDefault.IsThis(theGateway);\par ?? \par ?? \cf5 // First we create a new Setter Injection Policy that\par ??\cf0 \cf5 // forces StructureMap to inject all public properties\par ??\cf0 \cf5 // where the PropertyType is IGateway\par ??\cf0 x.SetAllProperties(y =>\par ?? \{\par ?? y.OfType<\cf3 IGateway\cf0 >();\par ?? \});\par ?? \});\par ??\par ?? \cf5 // Create an instance of BuildUpTarget1\par ??\cf0 \cf4 var\cf0 target = \cf4 new\cf0 \cf3 BuildUpTarget1\cf0 ();\par ??\par ?? \cf5 // Now, call BuildUp() on target, and\par ??\cf0 \cf5 // we should see the Gateway property assigned\par ??\cf0 \cf3 ObjectFactory\cf0 .BuildUp(target);\par ??\par ?? target.Gateway.ShouldBeTheSameAs(theGateway);\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> + create_a_setter_rule_and_see_it_applied_in_BuildUp_through_ObjectFactory()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> theGateway = <span style="color: blue;">new</span> + <span style="color: #2b91af;">DefaultGateway</span>();</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + ObjectFactory</span>.Initialize(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.ForRequestedType<<span style="color: #2b91af;">IGateway</span>>().TheDefault.IsThis(theGateway);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// First we create a new Setter Injection Policy + that</span></p> + <p style="margin: 0px;"> + + <span style="color: green;">// forces StructureMap to inject all public + properties</span></p> + <p style="margin: 0px;"> + + <span style="color: green;">// where the PropertyType is IGateway</span></p> + <p style="margin: 0px;"> + + x.SetAllProperties(y =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + y.OfType<<span style="color: #2b91af;">IGateway</span>>();</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // Create an instance of BuildUpTarget1</span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> target = <span style="color: blue;">new</span> + <span style="color: #2b91af;">BuildUpTarget1</span>();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // Now, call BuildUp() on target, and</span></p> + <p style="margin: 0px;"> + <span style="color: green;"> + // we should see the Gateway property assigned</span></p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + ObjectFactory</span>.BuildUp(target);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + target.Gateway.ShouldBeTheSameAs(theGateway);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>BuildUp() also works with primitive properties (but I'm not sure how useful this + will really be):</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;\red163\green21\blue21;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassThatHasConnection\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf3 string\cf0 ConnectionString \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \}\par ??\par ?? [\cf4 TestFixture\cf0 ]\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 demo_the_BuildUp\par ??\cf0 \{\par ?? [\cf4 Test\cf0 ]\par ?? \cf3 public\cf0 \cf3 void\cf0 push_in_a_string_property()\par ?? \{\par ?? \cf5 // There is a limitation to this. As of StructureMap 2.5.2,\par ??\cf0 \cf5 // you can only use the .WithProperty().EqualTo() syntax\par ??\cf0 \cf5 // for BuildUp()\par ??\cf0 \cf5 // SetProperty() will not work at this time.\par ??\cf0 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.ForConcreteType<\cf4 ClassThatHasConnection\cf0 >().Configure\par ?? .WithProperty(o => o.ConnectionString).EqualTo(\cf6 "connect1"\cf0 );\par ??\par ?? \});\par ??\par ?? \cf3 var\cf0 @class = \cf3 new\cf0 \cf4 ClassThatHasConnection\cf0 ();\par ?? container.BuildUp(@class);\par ??\par ?? @class.ConnectionString.ShouldEqual(\cf6 "connect1"\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;">ClassThatHasConnection</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">string</span> ConnectionString { + <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">TestFixture</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">demo_the_BuildUp</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">Test</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">void</span> push_in_a_string_property()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;"> + // There is a limitation to this. As of StructureMap 2.5.2,</span></p> + <p style="margin: 0px;"> + <span style="color: green;"> + // you can only use the .WithProperty().EqualTo() syntax</span></p> + <p style="margin: 0px;"> + <span style="color: green;"> + // for BuildUp()</span></p> + <p style="margin: 0px;"> + <span style="color: green;"> + // SetProperty() will not work at this time.</span></p> + <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.ForConcreteType<<span style="color: #2b91af;">ClassThatHasConnection</span>>().Configure</p> + <p style="margin: 0px;"> + + .WithProperty(o => o.ConnectionString).EqualTo(<span style="color: #a31515;">"connect1"</span>);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> @class = <span style="color: blue;">new</span> + <span style="color: #2b91af;">ClassThatHasConnection</span>();</p> + <p style="margin: 0px;"> + container.BuildUp(@class);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + @class.ConnectionString.ShouldEqual(<span style="color: #a31515;">"connect1"</span>);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> <h2><a name="SetterPolicies"></a>Creating Policies for Setter Injection</h2> <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 Modified: trunk/Source/HTML/UsingSessionContext.htm =================================================================== --- trunk/Source/HTML/UsingSessionContext.htm 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/HTML/UsingSessionContext.htm 2009-01-11 22:43:11 UTC (rev 219) @@ -15,7 +15,7 @@ dependencies that will be used within that object request. The IContext interface is shown below:</p> <!-- -{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red128\green128\blue128;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IContext\par ??\cf0 \{\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets a reference to the \cf5 <see cref="BuildStack">\cf6 BuildStack\cf5 </see>\cf6 for this build session\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildStack\cf0 BuildStack \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The concrete type of the immediate parent object in the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 Type\cf0 ParentType \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Get the object of type T that is valid for this build session.\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T GetInstance<T>();\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets the root "frame" of the object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildFrame\cf0 Root \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The requested instance name of the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf3 string\cf0 RequestedName \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Register a default object for the given PluginType that will\par ??\cf0 \cf5 ///\cf6 be used throughout the rest of the current object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="pluginType"></param>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="defaultObject"></param>\par ??\cf0 \cf3 void\cf0 RegisterDefault(\cf4 Type\cf0 pluginType, \cf3 object\cf0 defaultObject);\par ?? \}} +{\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;\red128\green128\blue128;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IContext\par ??\cf0 \{\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets a reference to the \cf5 <see cref="BuildStack">\cf6 BuildStack\cf5 </see>\cf6 for this build session\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildStack\cf0 BuildStack \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The concrete type of the immediate parent object in the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 Type\cf0 ParentType \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Get the object of type T that is valid for this build session.\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T GetInstance<T>();\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Get the object of type T that is valid for this build session by name.\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T GetInstance<T>(\cf3 string\cf0 name);\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets the root "frame" of the object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildFrame\cf0 Root \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The requested instance name of the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf3 string\cf0 RequestedName \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Register a default object for the given PluginType that will\par ??\cf0 \cf5 ///\cf6 be used throughout the rest of the current object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="pluginType"></param>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="defaultObject"></param>\par ??\cf0 \cf3 void\cf0 RegisterDefault(\cf4 Type\cf0 pluginType, \cf3 object\cf0 defaultObject);\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Same as GetInstance, but can gracefully return null if \par ??\cf0 \cf5 ///\cf6 the Type does not already exist\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T TryGetInstance<T>() \cf3 where\cf0 T : \cf3 class\cf0 ;\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Same as GetInstance(name), but can gracefully return null if \par ??\cf0 \cf5 ///\cf6 the Type and name does not already exist\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="name"></param>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T TryGetInstance<T>(\cf3 string\cf0 name) \cf3 where\cf0 T : \cf3 class\cf0 ;\par ?? \}} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> <p style="margin: 0px;"> @@ -81,6 +81,28 @@ style="color: green;"> </span><span style="color: gray;"><summary></span></p> <p style="margin: 0px;"> <span style="color: gray;">///</span><span + style="color: green;"> Get the object of type T that is valid for this build + session by name.</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;"><typeparam + name="T"></typeparam></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;"> + T GetInstance<T>(<span style="color: blue;">string</span> + name);</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;"> Gets the root "frame" of the object request</span></p> <p style="margin: 0px;"> <span style="color: gray;">///</span><span @@ -131,10 +153,71 @@ RegisterDefault(<span style="color: #2b91af;">Type</span> pluginType, <span style="color: blue;">object</span> defaultObject);</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;"> Same as GetInstance, but can gracefully return null + if </span> + </p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> the Type does not already exist</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;"><typeparam + name="T"></typeparam></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;"> + T TryGetInstance<T>() <span style="color: blue;"> + where</span> T : <span style="color: blue;">class</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;"> Same as GetInstance(name), but can gracefully return + null if </span> + </p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> the Type and name does not already exist</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;"><typeparam + name="T"></typeparam></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><param + name="name"></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;"> + T TryGetInstance<T>(<span style="color: blue;">string</span> + name) <span style="color: blue;">where</span> T : <span style="color: blue;"> + class</span>;</p> + <p style="margin: 0px;"> }</p> </div> <!--EndFragment--> <!-- +{\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;\red128\green128\blue128;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IContext\par ??\cf0 \{\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets a reference to the \cf5 <see cref="BuildStack">\cf6 BuildStack\cf5 </see>\cf6 for this build session\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildStack\cf0 BuildStack \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The concrete type of the immediate parent object in the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 Type\cf0 ParentType \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Get the object of type T that is valid for this build session.\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T GetInstance<T>();\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets the root "frame" of the object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildFrame\cf0 Root \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The requested instance name of the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf3 string\cf0 RequestedName \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Register a default object for the given PluginType that will\par ??\cf0 \cf5 ///\cf6 be used throughout the rest of the current object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="pluginType"></param>\par ??\cf0 \cf5 ///\cf6 \cf5 <param name="defaultObject"></param>\par ??\cf0 \cf3 void\cf0 RegisterDefault(\cf4 Type\cf0 pluginType, \cf3 object\cf0 defaultObject);\par ?? \}} +--> +<!--EndFragment--> +<!-- {\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;\red128\green128\blue128;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IContext\par ??\cf0 \{\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets a reference to the \cf5 <see cref="BuildStack">\cf6 BuildStack\cf5 </see>\cf6 for this build session\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildStack\cf0 BuildStack \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The concrete type of the immediate parent object in the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 Type\cf0 ParentType \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Get the object of type T that is valid for this build session.\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf5 ///\cf6 \cf5 <typeparam name="T"></typeparam>\par ??\cf0 \cf5 ///\cf6 \cf5 <returns></returns>\par ??\cf0 T GetInstance<T>();\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 Gets the root "frame" of the object request\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf4 BuildFrame\cf0 Root \{ \cf3 get\cf0 ; \}\par ??\par ?? \cf5 ///\cf6 \cf5 <summary>\par ??\cf0 \cf5 ///\cf6 The requested instance name of the object graph\par ??\cf0 \cf5 ///\cf6 \cf5 </summary>\par ??\cf0 \cf3 string\cf0 RequestedName \{ \cf3 get\cf0 ; \}\par ?? \}} --> <!--EndFragment--> Modified: trunk/Source/StructureMap/BuildSession.cs =================================================================== --- trunk/Source/StructureMap/BuildSession.cs 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/StructureMap/BuildSession.cs 2009-01-11 22:43:11 UTC (rev 219) @@ -27,6 +27,13 @@ T GetInstance<T>(); /// <summary> + /// Get the object of type T that is valid for this build session by name. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + T GetInstance<T>(string name); + + /// <summary> /// Gets the root "frame" of the object request /// </summary> BuildFrame Root { get; } @@ -43,6 +50,23 @@ /// <param name="pluginType"></param> /// <param name="defaultObject"></param> void RegisterDefault(Type pluginType, object defaultObject); + + /// <summary> + /// Same as GetInstance, but can gracefully return null if + /// the Type does not already exist + /// </summary> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + T TryGetInstance<T>() where T : class; + + /// <summary> + /// Same as GetInstance(name), but can gracefully return null if + /// the Type and name does not already exist + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="name"></param> + /// <returns></returns> + T TryGetInstance<T>(string name) where T : class; } public class BuildSession : IContext @@ -105,6 +129,11 @@ return (T) CreateInstance(typeof (T)); } + public T GetInstance<T>(string name) + { + return (T) CreateInstance(typeof (T), name); + } + BuildFrame IContext.Root { get { return _buildStack.Root; } @@ -182,7 +211,24 @@ _defaults[pluginType] = defaultObject; } + public T TryGetInstance<T>() where T : class + { + if (_defaults.Has(typeof(T))) + { + return (T) _defaults[typeof (T)]; + } + return _pipelineGraph.HasDefaultForPluginType(typeof (T)) + ? ((IContext) this).GetInstance<T>() + : null; + } + + public T TryGetInstance<T>(string name) where T : class + { + return _pipelineGraph.HasInstance(typeof (T), name) ? ((IContext) this).GetInstance<T>(name) : null; + } + + private IInstanceFactory forType(Type pluginType) { return _pipelineGraph.ForType(pluginType); Modified: trunk/Source/StructureMap/Container.cs =================================================================== --- trunk/Source/StructureMap/Container.cs 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/StructureMap/Container.cs 2009-01-11 22:43:11 UTC (rev 219) @@ -228,7 +228,7 @@ /// <returns></returns> public object TryGetInstance(Type pluginType, string instanceKey) { - return _pipelineGraph.ForType(pluginType).FindInstance(instanceKey) == null + return !_pipelineGraph.HasInstance(pluginType, instanceKey) ? null : GetInstance(pluginType, instanceKey); } @@ -240,7 +240,7 @@ /// <returns></returns> public object TryGetInstance(Type pluginType) { - return !_pipelineGraph.PluginTypes.Any(p => p.PluginType == pluginType) + return !_pipelineGraph.HasDefaultForPluginType(pluginType) ? null : GetInstance(pluginType); } Modified: trunk/Source/StructureMap/PipelineGraph.cs =================================================================== --- trunk/Source/StructureMap/PipelineGraph.cs 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/StructureMap/PipelineGraph.cs 2009-01-11 22:43:11 UTC (rev 219) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using StructureMap.Diagnostics; using StructureMap.Graph; using StructureMap.Pipeline; @@ -206,5 +207,16 @@ return list; } + + public bool HasDefaultForPluginType(Type pluginType) + { + PluginTypeConfiguration configuration = PluginTypes.FirstOrDefault(p => p.PluginType == pluginType); + return configuration == null ? false : configuration.Default != null; + } + + public bool HasInstance(Type pluginType, string instanceKey) + { + return ForType(pluginType).FindInstance(instanceKey) != null; + } } } \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/BuildSessionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/BuildSessionTester.cs 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/StructureMap.Testing/BuildSessionTester.cs 2009-01-11 22:43:11 UTC (rev 219) @@ -187,6 +187,61 @@ session.CreateInstance(typeof (IGateway)); }); } + + [Test] + public void when_retrieving_with_try_get_instance_for_instance_that_does_not_exists() + { + var session = new BuildSession(new PluginGraph()); + session.TryGetInstance<IService>().ShouldBeNull(); + } + + [Test] + public void when_retrieving_by_try_get_instance_for_instance_that_does_exist() + { + var session = new BuildSession(); + var theService = new ColorService("red"); + session.RegisterDefault(typeof(IService), theService); + + session.TryGetInstance<IService>().ShouldBeTheSameAs(theService); + } + + [Test] + public void when_retrieving_by_try_get_named_instance_that_does_not_exist() + { + var session = new BuildSession(); + session.TryGetInstance<IService>("red").ShouldBeNull(); + } + + [Test] + public void when_retrieving_by_try_get_named_instance_that_does_exist() + { + var red = new ColorService("red"); + var green = new ColorService("green"); + + PluginGraph graph = new PluginGraph(); + PluginFamily family = graph.FindFamily(typeof(IService)); + family.AddInstance(new LiteralInstance(red).WithName("red")); + family.AddInstance(new LiteralInstance(green).WithName("green")); + + var session = new BuildSession(graph); + session.TryGetInstance<IService>("red").ShouldBeTheSameAs(red); + session.TryGetInstance<IService>("green").ShouldBeTheSameAs(green); + } + + [Test] + public void when_retrieving_an_object_by_name() + { + var red = new ColorService("red"); + var green = new ColorService("green"); + + PluginGraph graph = new PluginGraph(); + PluginFamily family = graph.FindFamily(typeof(IService)); + family.AddInstance(new LiteralInstance(red).WithName("red")); + family.AddInstance(new LiteralInstance(green).WithName("green")); + + var session = new BuildSession(graph); + session.GetInstance<IService>("red").ShouldBeTheSameAs(red); + } } public interface IClassWithRule Modified: trunk/Source/StructureMap.Testing/BuildUpIntegratedTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/BuildUpIntegratedTester.cs 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/StructureMap.Testing/BuildUpIntegratedTester.cs 2009-01-11 22:43:11 UTC (rev 219) @@ -57,13 +57,21 @@ { x.IgnoreStructureMapConfig = true; x.ForRequestedType<IGateway>().TheDefault.IsThis(theGateway); + + // First we create a new Setter Injection Policy that + // forces StructureMap to inject all public properties + // where the PropertyType is IGateway x.SetAllProperties(y => { y.OfType<IGateway>(); }); }); + // Create an instance of BuildUpTarget1 var target = new BuildUpTarget1(); + + // Now, call BuildUp() on target, and + // we should see the Gateway property assigned ObjectFactory.BuildUp(target); target.Gateway.ShouldBeTheSameAs(theGateway); Added: trunk/Source/StructureMap.Testing/Examples/BuildUp.cs =================================================================== --- trunk/Source/StructureMap.Testing/Examples/BuildUp.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Examples/BuildUp.cs 2009-01-11 22:43:11 UTC (rev 219) @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; + +namespace StructureMap.Testing.Examples +{ + public class ClassThatHasConnection + { + public string ConnectionString { get; set; } + } + + [TestFixture] + public class demo_the_BuildUp + { + [Test] + public void push_in_a_string_property() + { + // There is a limitation to this. As of StructureMap 2.5.2, + // you can only use the .WithProperty().EqualTo() syntax + // for BuildUp() + // SetProperty() will not work at this time. + var container = new Container(x => + { + x.ForConcreteType<ClassThatHasConnection>().Configure + .WithProperty(o => o.ConnectionString).EqualTo("connect1"); + + }); + + var @class = new ClassThatHasConnection(); + container.BuildUp(@class); + + @class.ConnectionString.ShouldEqual("connect1"); + } + } +} Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj =================================================================== --- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-01-11 21:16:13 UTC (rev 218) +++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-01-11 22:43:11 UTC (rev 219) @@ -222,6 +222,7 @@ <Compile Include="Examples.cs"> <SubType>Form</SubType> </Compile> + <Compile Include="Examples\BuildUp.cs" /> <Compile Include="Examples\CustomInstance.cs" /> <Compile Include="Examples\Interception.cs" /> <Compile Include="Examples\RegisteringWithTheAPI.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |