From: <jer...@us...> - 2008-10-18 03:05:58
|
Revision: 184 http://structuremap.svn.sourceforge.net/structuremap/?rev=184&view=rev Author: jeremydmiller Date: 2008-10-18 03:05:42 +0000 (Sat, 18 Oct 2008) Log Message: ----------- html updates, ndoc type documentation, merged rhino mocker Modified Paths: -------------- trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/ScanningAssemblies.htm trunk/Source/StructureMap/BuildSession.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceExpression.cs trunk/Source/StructureMap/Configuration/DSL/Registry.cs trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/ExplicitArgsExpression.cs trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/PluginGraph.cs trunk/Source/StructureMap/IContainer.cs trunk/Source/StructureMap/Model.cs trunk/Source/StructureMap/ObjectFactory.cs trunk/Source/StructureMap/Pipeline/BuildStack.cs trunk/Source/StructureMap/Pipeline/Instance.cs trunk/Source/StructureMap/PipelineGraph.cs trunk/Source/StructureMap/StructureMapConfiguration.cs trunk/Source/StructureMap.AutoMocking/AutoMockedContainer.cs trunk/Source/StructureMap.AutoMocking/RhinoAutoMocker.cs trunk/Source/StructureMap.AutoMocking/ServiceLocator.cs trunk/Source/StructureMap.AutoMocking/StructureMap.AutoMocking.csproj trunk/Source/StructureMap.Testing/AutoMocking/RhinoAutoMockerTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/AddInstanceTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/DeepInstanceTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/InjectArrayTester.cs trunk/Source/StructureMap.Testing/Diagnostics/ValidationBuildSessionTester.cs trunk/Source/StructureMap.Testing/Graph/ContainerTester.cs trunk/Source/StructureMap.Testing/Graph/DynamicInjectionTester.cs trunk/Source/StructureMap.Testing/Graph/FullStackFacadeTester.cs trunk/Source/StructureMap.Testing/Graph/IntegratedTester.cs trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs trunk/Source/StructureMap.Testing/Pipeline/OptionalSetterInjectionTester.cs trunk/Source/StructureMap.sln Added Paths: ----------- trunk/Source/HTML/Example.xml trunk/Source/StructureMap.AutoMocking/AutoMocker.cs Modified: trunk/Source/HTML/ConstructorAndSetterInjection.htm =================================================================== --- trunk/Source/HTML/ConstructorAndSetterInjection.htm 2008-10-17 19:00:37 UTC (rev 183) +++ trunk/Source/HTML/ConstructorAndSetterInjection.htm 2008-10-18 03:05:42 UTC (rev 184) @@ -11,7 +11,7 @@ <ol> <li>Constructor Injection -- "Pushing" dependencies into a concrete class through constructor arguments.</li> - <li>Setter Injection -- "Pushing" depencencies into a concrete class through public + <li>Setter Injection -- "Pushing" dependencies into a concrete class through public properties. The "Setter" nomenclature is taken from Java where properties are getSomething() and setSomething(value).</li> </ol> @@ -24,7 +24,7 @@ Martin Fowler's discussion on Constructor versus Setter Injection</a> for more information. My feeling has always been that Constructor Injection is preferrable from a design perspective. When you exclusively use - Constructor Injection, the code is somewhat self-documenting because the + Constructor Injection, the code is somewhat more self-documenting because the constructor arguments will clearly delineate the dependencies of a concrete class. It's also important to think about the constructor method of a class being a contract. If you satisfy all of the arguments of the @@ -33,10 +33,14 @@ which setters need to be created externally to use the class. Of course, not using any form of Dependency Injection can be the worst answer because then you have no idea what it really takes to bootstrap the service. </p> + <p>Despite my personal distaste for Setter Injection, I gave into user demand and + greatly increased StructureMap's support for Setter Injection -- and promptly + found that support to be more useful than I thought it would be.</p> <h2>Using Constructor Injection</h2> <p>Now, the first question you might ask is how does StructureMap know which constructor function to use in a class that has multiple constructors? The - answer is that StructureMap will automatically select the "greediest" public + answer is that StructureMap will automatically select the "greediest" + <b>public</b> constructor of a class to use for injection. In this case, the "greediest" constructor is the constructor with the most arguments. In the case of a tie, StructureMap will use the first constructor that it encountered. For @@ -111,96 +115,357 @@ [InternalsVisibleTo] attribute to give StructureMap access to your own internal members. StructureMap 2.5 is now strongly signed (thanks to <a href="http://stevenharman.net/">Steve Harman</a>) partially for this - scenario. There is an architectural limitation </p> + scenario. </p> <h2>Using Setter Injection</h2> <p>Setter injection is a pattern of "injecting" dependencies via public properties. - Setter Injection with StructureMap is admittedly a second class citizen, but + Setter Injection with StructureMap is somewhat a second class citizen, but this is partially by design. My strong recommendation is to use constructor injection for all code that you control, and save setter injection - strictly for classes from external libraries where you do not have any control. </p> + strictly for classes from external libraries where you do not have any control. + As a summary, these are the Setter Injection features that are described in + detail below:</p> + <ul> + <li>By default, all public "Setters" are optional, meaning that these setters will + only be set if they are explicitly configured for a specific Instance</li> + <li>StructureMap can be directed to "auto wire" a property for a given Instance</li> + <li>Setters can be made mandatory by decorating the property with the + [SetterProperty] attribute</li> + <li>Any type that StructureMap can use in constructor arguments can be used for + setter properties</li> + <li>StructureMap can be directed to automatically inject the default value for any + property of a given type. This was added primarily for "optional" + dependencies like logging.</li> + <li>The StructureMap diagnostic tools will check for missing Setter values</li> + </ul> - <p>Ok, now that you've read that I don't believe that setter injection is a good - idea, but you're bound and determined to use it anyway, let's talk about how to - do it with StructureMap. First off, StructureMap needs to be explicitly - told to build a concrete class with each setter. These setter properties - are then considered to be mandatory anytime an Instance of that concrete type is - requested. StructureMap does not support optional setter properties (but - it could easily be done with the new post processing support). That - restriction may be relaxed in later versions.</p> - <p>Once StructureMap does know to use a setter in constructing a class, configuring - the actual property values is done no differently than constructor arguments.</p> - <p>Let's say you have a class called Repository with these properties:</p> - + <h4>Configuring Primitive Setter Properties</h4> + <p>Ok, now that you've read that I don't believe that setter injection is a good + idea, but you're bound and determined to use it anyway, let's talk about how to + do it with StructureMap. Let's say we have this class with a string + property called "Name":</p> <!-- -{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IDataProvider\cf0 \{\}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Repository\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 IDataProvider\cf0 _provider;\par ??\par ?? \cf3 public\cf0 \cf4 IDataProvider\cf0 Provider\par ?? \{\par ?? \cf3 set\par ??\cf0 \{\par ?? _provider = \cf3 value\cf0 ;\par ?? \}\par ?? \}\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;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 OptionalSetterTarget\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf3 string\cf0 Name \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 string\cf0 Name2 \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\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; border: black thin solid;"> <p style="margin: 0px;"> - </p> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">OptionalSetterTarget</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">string</span> Name { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>;; }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>I can specify the value of the "Name" property in the configuration API like + this:</p> <!-- -{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IDataProvider\cf0 \{\}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Repository\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 IDataProvider\cf0 _provider;\par ??\par ?? \cf3 public\cf0 \cf4 IDataProvider\cf0 Provider\par ?? \{\par ?? \cf3 set\par ??\cf0 \{\par ?? _provider = \cf3 value\cf0 ;\par ?? \}\par ?? \}\par ?? \}} +{\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;\red163\green21\blue21;}??\fs20 [\cf3 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 optional_setter_injection_with_string()\par ?? \{\par ?? \cf4 var\cf0 container = \cf4 new\cf0 \cf3 Container\cf0 (r =>\par ?? \{\par ?? \cf5 // The "Name" property is not configured for this instance\par ??\cf0 r.InstanceOf<\cf3 OptionalSetterTarget\cf0 >().Is.OfConcreteType<\cf3 OptionalSetterTarget\cf0 >().WithName(\cf6 "NoName"\cf0 );\par ??\par ?? \cf5 // The "Name" property is configured for this instance\par ??\cf0 r.ForConcreteType<\cf3 OptionalSetterTarget\cf0 >().Configure\par ?? .WithProperty(\cf6 "Name"\cf0 ).EqualTo(\cf6 "Jeremy"\cf0 );\par ?? \});\par ??\par ?? container.GetInstance<\cf3 OptionalSetterTarget\cf0 >().Name.ShouldEqual(\cf6 "Jeremy"\cf0 );\par ?? container.GetInstance<\cf3 OptionalSetterTarget\cf0 >(\cf6 "NoName"\cf0 ).Name.ShouldBeNull();\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; 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> optional_setter_injection_with_string()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(r =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: green;">// The "Name" property is not configured for this + instance</span></p> + <p style="margin: 0px;"> + + r.InstanceOf<<span style="color: #2b91af;">OptionalSetterTarget</span>>().Is.OfConcreteType<<span + style="color: #2b91af;">OptionalSetterTarget</span>>().WithName(<span + style="color: #a31515;">"NoName"</span>);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// The "Name" property is configured for this + instance</span></p> + <p style="margin: 0px;"> + + r.ForConcreteType<<span style="color: #2b91af;">OptionalSetterTarget</span>>().Configure</p> + <p style="margin: 0px;"> + + .WithProperty(<span style="color: #a31515;">"Name"</span>).EqualTo(<span + style="color: #a31515;">"Jeremy"</span>);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + container.GetInstance<<span style="color: #2b91af;">OptionalSetterTarget</span>>().Name.ShouldEqual(<span + style="color: #a31515;">"Jeremy"</span>);</p> + <p style="margin: 0px;"> + + container.GetInstance<<span style="color: #2b91af;">OptionalSetterTarget</span>>(<span + style="color: #a31515;">"NoName"</span>).Name.ShouldBeNull();</p> + <p style="margin: 0px;"> +& }</p> +</div> +<!--EndFragment--> +<p>In the case above I specified the value for the "Name" setter directly by + embedding the property value directly with the + WithProperty("Name").EqualTo("Jeremy"). You could also retrieve the value + for the property from the AppSettings portion of a .Net application config file + like this with the WithProperty("Name").EqualToAppSetting("name") syntax.</p> <!-- -{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IDataProvider\cf0 \{\}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Repository\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 IDataProvider\cf0 _provider;\par ??\par ?? \cf3 public\cf0 \cf4 IDataProvider\cf0 Provider\par ?? \{\par ?? \cf3 set\par ??\cf0 \{\par ?? _provider = \cf3 value\cf0 ;\par ?? \}\par ?? \}\par ??\par ??\par ?? \cf3 public\cf0 \cf3 bool\cf0 ShouldCache \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\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;\red0\green128\blue0;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (r =>\par ?? \{\par ?? \cf5 // The "Name" property is configured for this instance\par ??\cf0 r.ForConcreteType<\cf4 OptionalSetterTarget\cf0 >().Configure\par ?? .WithProperty(\cf6 "Name"\cf0 ).EqualToAppSetting(\cf6 "name"\cf0 );\par ?? \});} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> - <p style="margin: 0px;"> - <span style="color: blue;">public</span> <span style="color: blue;">interface</span> - <span style="color: #2b91af;">IDataProvider</span>{}</p> - <p style="margin: 0px;"> - </p> - <p style="margin: 0px;"> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(r =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + r.ForConcreteType<<span style="color: #2b91af;">OptionalSetterTarget</span>>().Configure</p> + <p style="margin: 0px;"> + + .WithProperty(<span style="color: #a31515;">"Name"</span>).EqualToAppSetting(<span + style="color: #a31515;">"name"</span>);</p> + <p style="margin: 0px;"> + });</p> +</div> +<!--EndFragment--> +<p>In both of the cases above the property name is designated by a string. + Using strings to designate property names is always going to be somewhat + problematic, so there's a new option in 2.5 to specify property values with a + Lambda expression (inspired by + <a href="http://www.udidahan.com/2008/06/13/external-value-configuration-with-ioc/"> + this post from Udi Dahan</a>) using an Action<T>.</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 r.ForConcreteType<\cf3 OptionalSetterTarget\cf0 >().Configure\par ?? .SetProperty(x => x.Name = \cf4 "Jeremy"\cf0 );} +--> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + r.ForConcreteType<<span style="color: #2b91af;">OptionalSetterTarget</span>>().Configure</p> + <p style="margin: 0px;"> + + .SetProperty(x => x.Name = <span style="color: #a31515;">"Jeremy"</span>);</p> +</div> +<!--EndFragment--> +<p>The value of the Lamdba expression mechanism is that it makes the configuration + static-typed with all of the advantages that static typing brings. This + action is executed on the object after creation. Technically, this + mechanism can be used to do anything to the new object before StructureMap + returns the new object to the code that requested it. There is no + limitation to the number of Action<T> handlers you can use. </p> +<p> </p> +<h4>Configuring Setter Dependencies</h4> + <p>Let's say you have a class that has a public property for a singular dependency + and another public property for an array of dependencies.</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 ClassWithDependency\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 Rule\cf0 Rule \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf4 Rule\cf0 [] Rules \{ \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;">Repository</span></p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">ClassWithDependency</span></p> + <p style="margin: 0px;"> {</p> - <p style="margin: 0px;"> - <span style="color: blue;">private</span> - <span style="color: #2b91af;">IDataProvider</span> _provider;</p> - <p style="margin: 0px;"> - </p> - <p style="margin: 0px;"> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: #2b91af;">IDataProvider</span> Provider</p> - <p style="margin: 0px;"> - {</p> - <p style="margin: 0px;"> - <span style="color: blue;">set</span></p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">Rule</span> Rule { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <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> + </div> +<!--EndFragment--> +<p>I can explicitly configure what gets injected into the "Rule" property for a + specific Instance of ClassWithDependency like this with the + .SetterDependency<T>() method that will look for the first public setter of type + T:</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;\red163\green21\blue21;}??\fs20 r.ForConcreteType<\cf3 ClassWithDependency\cf0 >().Configure\par ?? .SetterDependency<\cf3 Rule\cf0 >().Is(\cf4 new\cf0 \cf3 ColorRule\cf0 (\cf5 "Red"\cf0 ));} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + r.ForConcreteType<<span style="color: #2b91af;">ClassWithDependency</span>>().Configure</p> + <p style="margin: 0px;"> + + .SetterDependency<<span style="color: #2b91af;">Rule</span>>().Is(<span + style="color: blue;">new</span> <span style="color: #2b91af;">ColorRule</span>(<span + style="color: #a31515;">"Red"</span>));</p> +</div> +<!--EndFragment--> +<p>or for cases where a class may have multiple public setters of the same type, you + can specify the exact property with an Expression (.SetterDependency<T>( + expression ) ):</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (r =>\par ?? \{\par ?? r.ForConcreteType<\cf4 ClassWithDependency\cf0 >().Configure\par ?? .SetterDependency<\cf4 Rule\cf0 >().Is(\cf3 new\cf0 \cf4 ColorRule\cf0 (\cf5 "Red"\cf0 ));\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;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (r =>\par ?? \{\par ?? r.ForConcreteType<\cf4 ClassWithDependency\cf0 >().Configure\par ?? .SetterDependency<\cf4 Rule\cf0 >(x => x.Rule).Is(\cf3 new\cf0 \cf4 ColorRule\cf0 (\cf5 "Red"\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;">var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(r =></p> + <p style="margin: 0px;"> {</p> - <p style="margin: 0px;"> - _provider - = <span style="color: blue;">value</span>;</p> - <p style="margin: 0px;"> - }</p> - <p style="margin: 0px;"> - }</p> - <p style="margin: 0px;"> - </p> - <p style="margin: 0px;"> - </p> - <p style="margin: 0px;"> + <p style="margin: 0px;"> + + r.ForConcreteType<<span style="color: #2b91af;">ClassWithDependency</span>>().Configure</p> + <p style="margin: 0px;"> + + .SetterDependency<<span style="color: #2b91af;">Rule</span>>(x => x.Rule).Is(<span + style="color: blue;">new</span> <span style="color: #2b91af;">ColorRule</span>(<span + style="color: #a31515;">"Red"</span>));</p> + <p style="margin: 0px;"> + });</p> +</div> +<!--EndFragment--> +<p> </p> +<h4>"Auto Filling" a Setter Dependency</h4> +<p>Sometimes all you want to do is to simply say "fill in this property for me." + That's what the code below does for the "Rule" property with the + .SetterDependency<Rule>().IsTheDefault() syntax:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (r =>\par ?? \{\par ?? r.ForConcreteType<\cf4 ClassWithDependency\cf0 >().Configure\par ?? .SetterDependency<\cf4 Rule\cf0 >().IsTheDefault();\par ??\par ?? r.ForRequestedType<\cf4 Rule\cf0 >().TheDefault.Is.Object(\cf3 new\cf0 \cf4 ColorRule\cf0 (\cf5 "Green"\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;">var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(r =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + r.ForConcreteType<<span style="color: #2b91af;">ClassWithDependency</span>>().Configure</p> + <p style="margin: 0px;"> + + .SetterDependency<<span style="color: #2b91af;">Rule</span>>().IsTheDefault();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + r.ForRequestedType<<span style="color: #2b91af;">Rule</span>>().TheDefault.Is.Object(<span + style="color: blue;">new</span> <span style="color: #2b91af;">ColorRule</span>(<span + style="color: #a31515;">"Green"</span>));</p> + <p style="margin: 0px;"> + });</p> +</div> +<!--EndFragment--> +<p>For certain dependency types you might want StructureMap to automatically fill + any public property of that type. The first usage that comes to mind is + logging. Let's say that we have an interface for our logging support + called ILogger. We can specify that any concrete class that has a public + property for the ILogger type will be filled in construction with code like this + (FillAllPropertiesOfType<ILogger>()):</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (r =>\par ?? \{\par ?? r.FillAllPropertiesOfType<\cf4 ILogger\cf0 >().TheDefault.Is\par ?? .ConstructedBy(context => \cf3 new\cf0 \cf4 Logger\cf0 (context.ParentType));\par ?? \});} +--> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(r =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + r.FillAllPropertiesOfType<<span style="color: #2b91af;">ILogger</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .ConstructedBy(context => <span style="color: blue;">new</span> + <span style="color: #2b91af;">Logger</span>(context.ParentType));</p> + <p style="margin: 0px;"> + });</p> +</div> +<!--EndFragment--> +<p>Now, if I have some classes like:</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 ClassWithLogger\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 ILogger\cf0 Logger \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassWithLogger2\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 ILogger\cf0 Logger \{ \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;">ClassWithLogger</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: blue;">bool</span> ShouldCache { <span style="color: blue;"> - get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">ILogger</span> Logger { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> }</p> - </div> + <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;">ClassWithLogger2</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: #2b91af;">ILogger</span> Logger { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> + }</p> +</div> <!--EndFragment--> -<p style="margin: 0px;"> - </p> - </div> -<!--EndFragment--> +<p>Now, when StructureMap builds new instances of these classes above the Logger + properties will be filled automatically without any explicit configuration for + either type. Here's a sample from the unit tests that constructs objects + of both ClassWithLogger and ClassWithLogger2 and verifies that the "Logger" + property was filled for both types without any further configuration.</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 \par ?? container.GetInstance<\cf3 ClassWithLogger\cf0 >().Logger.ShouldBeOfType<\cf3 Logger\cf0 >().Type.ShouldEqual(\cf4 typeof\cf0 (\cf3 ClassWithLogger\cf0 ));\par ?? container.GetInstance<\cf3 ClassWithLogger2\cf0 >().Logger.ShouldBeOfType<\cf3 Logger\cf0 >().Type.ShouldEqual(\cf4 typeof\cf0 (\cf3 ClassWithLogger2\cf0 ));\par ??} +--> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + container.GetInstance<<span style="color: #2b91af;">ClassWithLogger</span>>().Logger.ShouldBeOfType<<span + style="color: #2b91af;">Logger</span>>();</p> + <p style="margin: 0px;"> + + container.GetInstance<<span style="color: #2b91af;">ClassWithLogger2</span>>().Logger.ShouldBeOfType<<span + style="color: #2b91af;">Logger</span>>();</p> + <p style="margin: 0px;"> + </p> </div> <!--EndFragment--> -<h4>Defining Setter Properties with Attributes</h4> -<p>Just use the [StructureMap.Attributes.SetterProperty] to denote properties that - need to be filled by StructureMap. If you despise scattering attributes in - your code, and the tight coupling </p> +<p> </p> + <!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 IDataProvider\cf0 \{\}\par ??\par ?? \cf3 public\cf0 \cf3 class\cf0 \cf4 Repository\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 IDataProvider\cf0 _provider;\par ??\par ?? \cf3 public\cf0 \cf4 IDataProvider\cf0 Provider\par ?? \{\par ?? \cf3 set\par ??\cf0 \{\par ?? _provider = \cf3 value\cf0 ;\par ?? \}\par ?? \}\par ?? \}} +--> +<!--EndFragment--> +<h4>Defining Setter Properties with Attributes<p>Just use the [StructureMap.Attributes.SetterProperty] to denote properties that + need to be filled by StructureMap. Marking a property with the + [SetterProperty] makes the setter mandatory. StructureMap will throw an + exception if the "ShouldCache" property isn't specified for the concrete type + shown below. If the "Provider" property isn't explicitly configured, + StructureMap will use the default instance of IDataProvider for the "Provider" + property (or throw an exception if StructureMap doesn't know how to build the + type IDataProvider). </p> +<!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 Repository\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf4 IDataProvider\cf0 _provider;\par ??\par ?? \cf5 // Adding the SetterProperty to a setter directs\par ??\cf0 \cf5 // StructureMap to use this property when\par ??\cf0 \cf5 // constructing a Repository instance\par ??\cf0 [\cf4 SetterProperty\cf0 ]\par ?? \cf3 public\cf0 \cf4 IDataProvider\cf0 Provider\par ?? \{\par ?? \cf3 set\par ??\cf0 \{\par ?? _provider = \cf3 value\cf0 ;\par ?? \}\par ?? \}\par ??\par ?? [\cf4 SetterProperty\cf0 ]\par ?? \cf3 public\cf0 \cf3 bool\cf0 ShouldCache \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \}} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> @@ -224,7 +489,7 @@ <span style="color: green;">// constructing a Repository instance</span></p> <p style="margin: 0px;"> - [<span style="color: #2b91af;">SetterProperty</span>]</p> + [<span style="color: #2b91af;">SetterProperty</span>]/p> <p style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: #2b91af;">IDataProvider</span> Provider</p> @@ -258,81 +523,124 @@ <h4>Defining Setter Properties in Xml</h4> <p>Setter properties can be defined in the Xml configuration by explicitly directing - StructureMap to use setter properties while building a concrete type. From + StructureMap to use setter properties while building a concrete type. In + the Xml, Setter configuration is done with the exact syntax as constructor + arguments. For example, the "Name" property of the OptionalSetterTarget + class shown in previous sections can be set just like a constructor argument in + an Xml node:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 <\cf3 StructureMap\cf1 \cf4 MementoStyle\cf1 =\cf0 "\cf1 Attribute\cf0 "\cf1 >\par ?? <\cf3 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Pipeline.OptionalSetterTarget, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Pipeline.OptionalSetterTarget, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 Name\cf1 =\cf0 "\cf1 Jeremy\cf0 "\cf1 />\par ??</\cf3 StructureMap\cf1 >} +--> + <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;"> <</span><span style="color: #a31515;">StructureMap</span><span + style="color: blue;"> </span><span style="color: red;">MementoStyle</span><span + style="color: blue;">=</span>"<span style="color: blue;">Attribute</span>"<span + style="color: blue;">> </span> + </p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: #a31515;">DefaultInstance</span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </span> + <span style="color: red;">PluginType</span><span style="color: blue;">=</span>"<span + style="color: blue;">StructureMap.Testing.Pipeline.OptionalSetterTarget, + StructureMap.Testing</span>"</p> + <p style="margin: 0px;"> + <span style="color: blue;"> </span> + <span style="color: red;"> PluggedType</span><span style="color: blue;">=</span>"<span + style="color: blue;">StructureMap.Testing.Pipeline.OptionalSetterTarget, + StructureMap.Testing</span>"</p> + <p style="margin: 0px;"> + <span style="color: blue;"> </span> + <span style="color: red;"> Name</span><span style="color: blue;">=</span>"<span + style="color: blue;">Jeremy</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </</span><span style="color: #a31515;">StructureMap</span><span + style="color: blue;">></span></p> + </div> +<!--EndFragment--> +<p> </p> +<p>Setter properties can also be designated as mandatory setters with the <Setter> + node in the Xml configuration. From the unit tests, I have a class called OtherGridColumn that exposes several properties:</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 OtherGridColumn\cf0 : \cf4 IGridColumn\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 IWidget\cf0 Widget \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ??\par ?? \cf3 public\cf0 \cf3 string\cf0 ReadOnly\par ?? \{\par ?? \cf3 get\par ??\cf0 \{\par ?? \cf3 return\cf0 \cf5 "whatever"\cf0 ;\par ?? \}\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf4 FontStyleEnum\cf0 FontStyle \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 string\cf0 ColumnName \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf4 Rule\cf0 [] Rules \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 bool\cf0 WrapLines \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 bool\cf0 Displayed \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 int\cf0 Size \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \}} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> - <p style="margin: 0px;"> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 OtherGridColumn\cf0 : \cf4 IGridColumn\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf4 IWidget\cf0 Widget \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ??\par ?? \cf3 public\cf0 \cf3 string\cf0 ReadOnly\par ?? \{\par ?? \cf3 get\cf0 \{ \cf3 return\cf0 \cf5 "whatever"\cf0 ; \}\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf4 FontStyleEnum\cf0 FontStyle \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 string\cf0 ColumnName \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf4 Rule\cf0 [] Rules \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 bool\cf0 WrapLines \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 bool\cf0 Displayed \{ \cf3 get\cf0 ; \cf3 set\cf0 ; \}\par ?? \cf3 public\cf0 \cf3 int\cf0 Size \{ \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;">OtherGridColumn</span> : - <span style="color: #2b91af;">IGridColumn</span></p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">OtherGridColumn</span> : + <span style="color: #2b91af;">IGridColumn</span></p> + <p style="margin: 0px;"> {</p> - <p style="margin: 0px;"> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: #2b91af;">IWidget</span> Widget { <span style="color: blue;"> - get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> - </p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">IWidget</span> Widget { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: blue;">string</span> ReadOnly</p> - <p style="margin: 0px;"> + <span style="color: blue;">string</span> ReadOnly</p> + <p style="margin: 0px;"> {</p> - <p style="margin: 0px;"> - - <span style="color: blue;">get</span></p> - <p style="margin: 0px;"> - {</p> - <p style="margin: 0px;"> - - <span style="color: blue;">return</span> <span style="color: #a31515;"> - "whatever"</span>;</p> - <p style="margin: 0px;"> - }</p> - <p style="margin: 0px;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + get</span> { <span style="color: blue;">return</span> + <span style="color: #a31515;">"whatever"</span>; }</p> + <p style="margin: 0px;"> }</p> - <p style="margin: 0px;"> - </p> - <p style="margin: 0px;"> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: #2b91af;">FontStyleEnum</span> FontStyle { - <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">FontStyleEnum</span> FontStyle { + <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: blue;">string</span> ColumnName { <span style="color: blue;"> - get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: blue;">string</span> ColumnName { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: #2b91af;">Rule</span>[] Rules { <span style="color: blue;"> - get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: #2b91af;">Rule</span>[] Rules { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: blue;">bool</span> WrapLines { <span style="color: blue;"> - get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: blue;">bool</span> WrapLines { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: blue;">bool</span> Displayed { <span style="color: blue;"> - get</span>; <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: blue;">bool</span> Displayed { <span style="color: blue;"> + get</span>; <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> <span style="color: blue;">public</span> - <span style="color: blue;">int</span> Size { <span style="color: blue;">get</span>; - <span style="color: blue;">set</span>; }</p> - <p style="margin: 0px;"> + <span style="color: blue;">int</span> Size { <span style="color: blue;">get</span>; + <span style="color: blue;">set</span>; }</p> + <p style="margin: 0px;"> }</p> + </div> +<!--EndFragment--> +<p style="margin: 0px;"> + </p> </div> <!--EndFragment--> -<p>I can direct StructureMap to use these properties in a <Plugin> node for - OtherGridColumn.</p> +<p>I can direct StructureMap to make the properties on the OtherGridColumn class + mandatory in a <Plugin> node for + OtherGridColumn. This probably isn't necessary with the new optional + setter injection capabilities, but it is still valid and the equivalent of using + the [SetterProperty] attribute.</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue255;\red255\green255\blue255;\red163\green21\blue21;\red255\green0\blue0;\red0\green0\blue0;}??\fs20 \cf1 \tab <\cf3 PluginFamily\cf1 \cf4 Type\cf1 =\cf0 "\cf1 StructureMap.Testing.Widget5.IGridColumn\cf0 "\cf1 \cf4 Assembly\cf1 =\cf0 "\cf1 StructureMap.Testing.Widget5\cf0 "\cf1 \cf4 DefaultKey\cf1 =\cf0 ""\cf1 >\par ??\tab \tab <\cf3 Source\cf1 \cf4 Type\cf1 =\cf0 "\cf1 XmlFile\cf0 "\cf1 \cf4 FilePath\cf1 =\cf0 "\cf1 GridColumnInstances.xml\cf0 "\cf1 \cf4 XPath\cf1 =\cf0 "\cf1 //GridColumns\cf0 "\cf1 \cf4 NodeName\cf1 =\cf0 "\cf1 GridColumn\cf0 "\cf1 />\par ??\tab \tab <\cf3 Plugin\cf1 \cf4 Assembly\cf1 =\cf0 "\cf1 StructureMap.Testing.Widget5\cf0 "\cf1 \cf4 Type\cf1 =\cf0 "\cf1 StructureMap.Testing.Widget5.OtherGridColumn\cf0 "\cf1 \cf4 ConcreteKey\cf1 =\cf0 "\cf1 Other\cf0 "\cf1 >\par ??\tab \tab \tab <\cf3 Setter\cf1 \cf4 Name\cf1 =\cf0 "\cf1 ColumnName\cf0 "\cf1 />\par ??\tab \tab \tab <\cf3 Setter\cf1 \cf4 Name\cf1 =\cf0 "\cf1 FontStyle\cf0 "\cf1 />\par ??\tab \tab \tab <\cf3 Setter\cf1 \cf4 Name\cf1 =\cf0 "\cf1 Rules\cf0 "\cf1 />\par ??\tab \tab \tab <\cf3 Setter\cf1 \cf4 Name\cf1 =\cf0 "\cf1 Widget\cf0 "\cf1 />\par ??\tab \tab \tab <\cf3 Setter\cf1 \cf4 Name\cf1 =\cf0 "\cf1 WrapLines\cf0 "\cf1 />\par ??\tab \tab </\cf3 Plugin\cf1 >\par ??\tab </\cf3 PluginFamily\cf1 >} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> <p style="margin: 0px;"> - <span style="color: blue;"> <</span><span style="color: #a31515;">PluginFamily</span><span + <span style="color: blue;"> <</span><span style="color: #a31515;">PluginFamily/span><span style="color: blue;"> </span><span style="color: red;">Type</span><span style="color: blue;">=</span>"<span style="color: blue;">StructureMap.Testing.Widget5.IGridColumn</span>"<span style="color: blue;"> </span><span style="color: red;">Assembly</span><span @@ -379,13 +687,10 @@ style="color: #a31515;">Plugin</span><span style="color: blue;">></span></p> <p style="margin: 0px;"> <span style="color: blue;"> </</span><span style="color: #a31515;">PluginFamily</span><span - style="color: blue;">></span></p> + style="color: blue;">&></span></p> </div> <!--EndFragment--> <p> </p> - <h4>Defining Setter Properties with the Fluent Interface</h4> - <p>This isn't possible today, except with a post processing method. This - feature will be added in the next minor release.</p> - </body> + </body> </html> \ No newline at end of file Added: trunk/Source/HTML/Example.xml =================================================================== --- trunk/Source/HTML/Example.xml (rev 0) +++ trunk/Source/HTML/Example.xml 2008-10-18 03:05:42 UTC (rev 184) @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" ?> +<StructureMap MementoStyle="Attribute"> + <DefaultInstance + PluginType="StructureMap.Testing.Pipeline.OptionalSetterTarget, StructureMap.Testing" + PluggedType="StructureMap.Testing.Pipeline.OptionalSetterTarget, StructureMap.Testing" + Name="Jeremy" /> +</StructureMap> \ No newline at end of file Modified: trunk/Source/HTML/HTML.csproj =================================================================== --- trunk/Source/HTML/HTML.csproj 2008-10-17 19:00:37 UTC (rev 183) +++ trunk/Source/HTML/HTML.csproj 2008-10-18 03:05:42 UTC (rev 184) @@ -62,6 +62,7 @@ <Content Include="BestPractices.htm" /> <Content Include="ChangingDefaultsAtRuntime.htm" /> <Content Include="CompositeConfiguration.htm" /> + <Content Include="Example.xml" /> <Content Include="Glossary.htm" /> <Content Include="ConcreteTypes.htm" /> <Content Include="ConfigurationArchitecture.htm" /> Modified: trunk/Source/HTML/ScanningAssemblies.htm =================================================================== --- trunk/Source/HTML/ScanningAssemblies.htm 2008-10-17 19:00:37 UTC (rev 183) +++ trunk/Source/HTML/ScanningAssemblies.htm 2008-10-18 03:05:42 UTC (rev 184) @@ -1,9 +1,406 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>Auto Registration with Type Scanning</title> </head> <body> - + <h1>Auto Registration with Type Scanning</h1> + + <p> + StructureMap has always had some ability to register types by by scanning + assemblies (auto registration). The original version of StructureMap circa + 2004 looked for types decorated with specific attributes. Version 2.0 + added the ability to look for Registry classes within those assemblies. + The auto registration mechanism has been completely revamped in StructureMap 2.5 + with greatly extended capabilities. The downside is that the "scanning" + syntax in v2.5 is completely incompatible with previous versions, including the + 2.4.9 preview release. However, the Xml configuration has remained + consistent in both form and function.</p> + <h4> + Table of Contents</h4> + <ul> + <li>The Scan() Expression</li> + </ul> + <h4> + Using the Scan() Expression</h4> + <p> + Auto registration begins with the Scan() expression inside a Registry class or + the now deprecated StructureMapConfiguration class. Here's an example from + my current project:</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;}??\fs20 Scan(x =>\par ?? \{\par ?? x.TheCallingAssembly();\par ??\par ?? x.ExcludeNamespaceContainingType<\cf3 IEvent\cf0 >();\par ?? x.ExcludeNamespaceContainingType<\cf3 SearchModel\cf0 >();\par ?? x.ExcludeNamespaceContainingType<\cf3 AuthenticationService\cf0 >();\par ?? x.ExcludeNamespaceContainingType<\cf3 DovetailController\cf0 >();\par ??\par ?? x.AddAllTypesOf<\cf3 IDomainMap\cf0 >();\par ?? \par ?? x.WithDefaultConventions();\par ?? x.With<\cf3 DomainEntityAliaser\cf0 >();\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + ... [truncated message content] |