You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
(5) |
Mar
(9) |
Apr
(9) |
May
(4) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(3) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
|
Apr
(16) |
May
(28) |
Jun
(13) |
Jul
(3) |
Aug
(19) |
Sep
(11) |
Oct
(37) |
Nov
(1) |
Dec
(17) |
2009 |
Jan
(16) |
Feb
(6) |
Mar
|
Apr
(6) |
May
(1) |
Jun
(10) |
Jul
(4) |
Aug
(4) |
Sep
(4) |
Oct
(8) |
Nov
(3) |
Dec
(45) |
2010 |
Jan
(8) |
Feb
(21) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
(1) |
Oct
|
Nov
|
Dec
|
From: <jer...@us...> - 2009-01-19 18:57:40
|
Revision: 225 http://structuremap.svn.sourceforge.net/structuremap/?rev=225&view=rev Author: jeremydmiller Date: 2009-01-19 18:57:33 +0000 (Mon, 19 Jan 2009) Log Message: ----------- some attribute changes for Azure support Modified Paths: -------------- trunk/Source/StructureMap/ObjectFactory.cs trunk/Source/StructureMap/Properties/AssemblyInfo.cs trunk/Source/StructureMap.Testing/Configuration/ProfileBuilderTester.cs Modified: trunk/Source/StructureMap/ObjectFactory.cs =================================================================== --- trunk/Source/StructureMap/ObjectFactory.cs 2009-01-19 18:49:29 UTC (rev 224) +++ trunk/Source/StructureMap/ObjectFactory.cs 2009-01-19 18:57:33 UTC (rev 225) @@ -12,7 +12,7 @@ /// <summary> /// The main static Facade for the StructureMap container /// </summary> - [EnvironmentPermission(SecurityAction.Assert, Read = "COMPUTERNAME")] + //[EnvironmentPermission(SecurityAction.Assert, Read = "COMPUTERNAME")] public static class ObjectFactory { private static readonly object _lockObject = new object(); Modified: trunk/Source/StructureMap/Properties/AssemblyInfo.cs =================================================================== --- trunk/Source/StructureMap/Properties/AssemblyInfo.cs 2009-01-19 18:49:29 UTC (rev 224) +++ trunk/Source/StructureMap/Properties/AssemblyInfo.cs 2009-01-19 18:57:33 UTC (rev 225) @@ -1,5 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; +using System.Security; // // General Information about an assembly is controlled through the following @@ -16,4 +17,6 @@ [assembly: InternalsVisibleTo( "StructureMap.Testing, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d9a2a76e43cd9b1b1944b1f3b489a046b33f0bcd755b25cc5d3ed7b18ded38240d6db7578cd986c72d3feb4f94a7ab26fcfa41e3e4f41cf2c029fba91159db05c44d63f0b2bfac24353a07f4a1230dd3d4240340adafa2275277fa083c75958062cd0e60016701db6af7ae718efdf1e802a840595b49c290964255b3c60c494" - )] \ No newline at end of file + )] + +[assembly: AllowPartiallyTrustedCallers] \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/Configuration/ProfileBuilderTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/ProfileBuilderTester.cs 2009-01-19 18:49:29 UTC (rev 224) +++ trunk/Source/StructureMap.Testing/Configuration/ProfileBuilderTester.cs 2009-01-19 18:57:33 UTC (rev 225) @@ -22,6 +22,12 @@ private PluginGraph _graph; private ProfileBuilder _builder; private const string THE_MACHINE_NAME = "TheMachineName"; + + [Test] + public void smoke_test_get_machine_name() + { + ProfileBuilder.GetMachineName().ShouldNotBeEmpty(); + } [Test] public void Do_not_register_a_machine_override_if_it_is_NOT_the_matching_machine() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2009-01-19 18:49:36
|
Revision: 224 http://structuremap.svn.sourceforge.net/structuremap/?rev=224&view=rev Author: jeremydmiller Date: 2009-01-19 18:49:29 +0000 (Mon, 19 Jan 2009) Log Message: ----------- some new cleanup methods Modified Paths: -------------- trunk/Source/CommonAssemblyInfo.cs trunk/Source/HTML/QuickStart.htm trunk/Source/HTML/ToC-Bullet-List.xml trunk/Source/HTML/structuremap.js trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/ExplicitArgsExpression.cs trunk/Source/StructureMap/IContainer.cs trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs trunk/Source/StructureMap/Pipeline/IBuildInterceptor.cs trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs trunk/Source/StructureMap/Pipeline/ThreadLocalStoragePolicy.cs trunk/Source/StructureMap/Util/Cache.cs trunk/Source/StructureMap.Testing/Graph/ContainerTester.cs trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs trunk/Source/TableOfContentsBuilder/Program.cs trunk/cruise.build Modified: trunk/Source/CommonAssemblyInfo.cs =================================================================== --- trunk/Source/CommonAssemblyInfo.cs 2009-01-15 16:02:34 UTC (rev 223) +++ trunk/Source/CommonAssemblyInfo.cs 2009-01-19 18:49:29 UTC (rev 224) @@ -13,11 +13,11 @@ //------------------------------------------------------------------------------ [assembly: ComVisibleAttribute(false)] -[assembly: AssemblyVersionAttribute("2.5.2.0000")] +[assembly: AssemblyVersionAttribute("2.5.3.0000")] [assembly: AssemblyCopyrightAttribute("Copyright (c) 2003-2008, Jeremy D. Miller")] [assembly: AssemblyProductAttribute("StructureMap")] [assembly: AssemblyCompanyAttribute("")] [assembly: AssemblyConfigurationAttribute("release")] -[assembly: AssemblyInformationalVersionAttribute("2.5.2.0000")] -[assembly: AssemblyFileVersionAttribute("2.5.2.0000")] +[assembly: AssemblyInformationalVersionAttribute("2.5.3.0000")] +[assembly: AssemblyFileVersionAttribute("2.5.3.0000")] Modified: trunk/Source/HTML/QuickStart.htm =================================================================== --- trunk/Source/HTML/QuickStart.htm 2009-01-15 16:02:34 UTC (rev 223) +++ trunk/Source/HTML/QuickStart.htm 2009-01-19 18:49:29 UTC (rev 224) @@ -10,15 +10,15 @@ <body> <p> - The most general question I get with StructureMap is “how do I get started?” - I’d recommend that you first get comfortable + The most general question I get with StructureMap is "how do I get started?" + I'd recommend that you first get comfortable <a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/06/29/some-concepts-to-know-first.aspx"> with some concepts</a> and the basic patterns of <a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx"> Dependency Injection</a> and <a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/09/20/132290.aspx"> - Inversion of Control</a>. Assuming that you’re already familiar with those - concepts, or you’d really rather skip the pedantry and jump right into concrete + Inversion of Control</a>. Assuming that you're already familiar with those + concepts, or you'd really rather skip the pedantry and jump right into concrete code, the first thing to do is go download StructureMap and jump into usage (then come back to the patterns and pedantry). </p> @@ -43,7 +43,7 @@ <li>StructureMap is actually the oldest IoC tool for .Net, with the first production release coming in June of 2004 </li> <li>The source code is accessible - <a href="https://structuremap.svn.sourceforge.net/svnroot/structuremap/trunk">here via Subversion</a> in case you’re curious. No credentials are required to + <a href="https://structuremap.svn.sourceforge.net/svnroot/structuremap/trunk">here via Subversion</a> in case you're curious. No credentials are required to access the source code. </li> <li>Right now, StructureMap 2.5 will run on .Net 3.5 only. I will most likely NOT be backporting the new version to 2.0 because of extensive usage of 3.5 features @@ -57,11 +57,11 @@ Your interaction with StructureMap is going to mostly consist of two activities:</p> <ol> <li>Asking StructureMap for an instance of a service or dependency (the easy part) </li> - <li>Registering “what” and “how” StructureMap should build or find those requested - services (the tedious part, but it’s gotten much better over the years) </li> + <li>Registering "what" and "how" StructureMap should build or find those requested + services (the tedious part, but it's gotten much better over the years) </li> </ol> <p> - In our system we use a service called “IValidator” to exercise validation rules + In our system we use a service called "IValidator" to exercise validation rules on our domain model objects (I talked about the approach <a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/06/13/build-your-own-cab-part-9-domain-centric-validation-with-the-notification-pattern.aspx"> here</a>). By default, we want any consumer of the IValidator interface to @@ -148,10 +148,10 @@ }</p> </div> <p> - That’s it, your first usage of StructureMap. No messy Xml configuration, + That's it, your first usage of StructureMap. No messy Xml configuration, no attributes scattered through your code, just a couple lines of bootstrapping - code. Of course, if that’s all StructureMap did, it wouldn’t be - worth your time to download it. Let’s look at a bit more advanced example.</p> + code. Of course, if that's all StructureMap did, it wouldn't be + worth your time to download it. Let's look at a bit more advanced example.</p> <hr /> <h2> Primitive Arguments</h2> @@ -159,7 +159,7 @@ I actually like to <a href="http://structuremap.sourceforge.net/ConfigurationManagement.htm">use StructureMap as a generic configuration tool</a> (which was actually its - original purpose). Let’s say you’re moving to the data access code. + original purpose). Let's say you're moving to the data access code. You come up with some sort of <a href="http://martinfowler.com/eaaCatalog/repository.html">Repository</a> pattern class like this:</p> @@ -212,7 +212,7 @@ }</p> </div> <p> - The Repository class needs to be supplied with the “connectionString” in its + The Repository class needs to be supplied with the "connectionString" in its constructor. No problem, just set up the value of the constructor argument in the bootstrapping:</p> <div style="BORDER-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"> @@ -260,10 +260,10 @@ style="COLOR: #2b91af">IRepository</span>>();</p> </div> <p> - StructureMap will look up the “CONNECTION-STRING” value in the AppSettings + StructureMap will look up the "CONNECTION-STRING" value in the AppSettings portion of the App.config file, and use that string value to invoke the constructor function of the Repository class, then hand back that new Repository - object. Woo hoo. We can build an object that doesn’t depend on + object. Woo hoo. We can build an object that doesn't depend on anything, and we can build an object that needs some strings in its constructor function. How about objects that need other non-primitive objects?</p> <hr /> @@ -271,15 +271,15 @@ Auto Wiring</h2> <p> In the code samples above, I used StructureMap as a Service Locator in the - ClassThatGetsAnIValidator.SaveObject() method. Typically, you’ll try to + ClassThatGetsAnIValidator.SaveObject() method. Typically, you'll try to minimize the number of service locator 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 + (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 + 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:</p> + Repository. Here's a representative Controller class:</p> <div style="BORDER-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"> <span style="COLOR: blue">public</span> <span style="COLOR: blue">class</span> @@ -318,7 +318,7 @@ }</p> </div> <p> - So let’s get StructureMap set up for this SomeScreenController class:</p> + So let's get StructureMap set up for this SomeScreenController class:</p> <div style="BORDER-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"> <span style="COLOR: #2b91af"> @@ -349,7 +349,7 @@ });</p> </div> <p> - You’ll notice that we didn’t make any explicit configuration for the + You'll notice that we didn't make any explicit configuration for the SomeScreenController class, but yet we could now call:</p> <div style="BORDER-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"> @@ -361,17 +361,17 @@ and StructureMap will happily create a new instance of the SomeScreenController class by invoking its constructor and passing in a new Validator object and a new Repository object created with the connection string from the App.config - file. We didn’t need to tell StructureMap how to construct + file. We didn't need to tell StructureMap how to construct SomeScreenController because: </p> <ul> <li>StructureMap can look at the constructor function of SomeScreenController and see that it depends on IValidator and IRepository </li> - <li>StructureMap “knows” about the default way to create and return an IValidator + <li>StructureMap "knows" about the default way to create and return an IValidator and an IRepository </li> </ul> <p> - This feature is known as “auto wiring,” and all the mainstream IoC containers + This feature is known as "auto wiring," and all the mainstream IoC containers support this feature to some extent or another. </p> <hr /> @@ -379,13 +379,13 @@ What to do when things go wrong?</h2> <p> StructureMap, and any other IoC tool for that matter, is configuration intensive - – which means that their will be problems in that configuration. We’re all + – which means that their will be problems in that configuration. We're all moving to more convention based type registration – which means that more stuff is happening off stage and out of your sight, making debugging the configuration even trickier. Not to worry (too much), StructureMap has some diagnostic abilities to help you solve configuration problems. The quickest tool is to ask a Container object or ObjectFactory (which is just a static wrapper - around a Container) “what do you have?” with the Container.WhatDoIHave() method + around a Container) "what do you have?" with the Container.WhatDoIHave() method like this below:</p> <div style="BORDER-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"> @@ -440,7 +440,7 @@ <p> which is admittedly, not the prettiest looking thing in the world.</p> <p> - You can also “assert” that the configuration for a Container or ObjectFactory is + You can also "assert" that the configuration for a Container or ObjectFactory is complete by calling the Container.AssertConfigurationIsValid() method like this sample below:</p> <div style="BORDER-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"> @@ -479,7 +479,7 @@ <ol> <li>Look for any missing constructor or mandatory setter arguments </li> <li>Look for any unknown dependency types </li> - <li>Look for any errors in the Xml configuration (if you’re using Xml configuration) + <li>Look for any errors in the Xml configuration (if you're using Xml configuration) </li> <li>Try to build each and every type and named instance in the configuration – i.e. this is a complete, but relatively expensive operation </li> @@ -488,8 +488,8 @@ feature that is unique to StructureMap as far as I know</a>) </li> </ol> <p> - The previous sample is a valid configuration, but let’s look at an invalid - configuration. Let’s omit the configuration of the “connectionString” + The previous sample is a valid configuration, but let's look at an invalid + configuration. Let's omit the configuration of the "connectionString" constructor argument for the Repository class and try AssertConfigurationIsValid():</p> <div style="BORDER-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"> @@ -534,8 +534,8 @@ StructureMap.StructureMapException: StructureMap Exception Code: 205 Missing requested Instance property "connectionString" for InstanceKey "73b7f21b-bbfd-462c-854d-5b2a2f98ba50"</pre> <p> - which again, isn’t the prettiest thing in the world, but it does tell me that - the “connectionString” argument is missing for the Repository class. After + which again, isn't the prettiest thing in the world, but it does tell me that + the "connectionString" argument is missing for the Repository class. After seeing this output, I think that this output and error wording will get improved in an upcoming release.</p> <hr /> Modified: trunk/Source/HTML/ToC-Bullet-List.xml =================================================================== --- trunk/Source/HTML/ToC-Bullet-List.xml 2009-01-15 16:02:34 UTC (rev 223) +++ trunk/Source/HTML/ToC-Bullet-List.xml 2009-01-19 18:49:29 UTC (rev 224) @@ -1,834 +1,834 @@ <div> <ul> <li> - <a href="default.htm">Home</a> + <a href="http://structuremap.sourceforge.net/default.htm">Home</a> <ul> <li> - <a href="default.htm#section0">Status</a> + <a href="http://structuremap.sourceforge.net/default.htm#section0">Status</a> <ul /> </li> <li> - <a href="default.htm#section1">Related Links:</a> + <a href="http://structuremap.sourceforge.net/default.htm#section1">Related Links:</a> <ul /> </li> </ul> </li> <li> - <a href="FeatureList.htm">Feature List</a> + <a href="http://structuremap.sourceforge.net/FeatureList.htm">Feature List</a> <ul /> </li> <li> - <a href="QuickStart.htm">A Gentle Quickstart</a> + <a href="http://structuremap.sourceforge.net/QuickStart.htm">A Gentle Quickstart</a> <ul> <li> - <a href="QuickStart.htm#section0">Salient Facts</a> + <a href="http://structuremap.sourceforge.net/QuickStart.htm#section0">Salient Facts</a> <ul /> </li> <li> - <a href="QuickStart.htm#section1">The Simplest Possible Usage of StructureMap</a> + <a href="http://structuremap.sourceforge.net/QuickStart.htm#section1">The Simplest Possible Usage of StructureMap</a> <ul /> </li> <li> - <a href="QuickStart.htm#section2">Primitive Arguments</a> + <a href="http://structuremap.sourceforge.net/QuickStart.htm#section2">Primitive Arguments</a> <ul /> </li> <li> - <a href="QuickStart.htm#section3">Auto Wiring</a> + <a href="http://structuremap.sourceforge.net/QuickStart.htm#section3">Auto Wiring</a> <ul /> </li> <li> - <a href="QuickStart.htm#section4">What to do when things go wrong?</a> + <a href="http://structuremap.sourceforge.net/QuickStart.htm#section4">What to do when things go wrong?</a> <ul /> </li> </ul> </li> <li> - <a href="Glossary.htm">Glossary</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm">Glossary</a> <ul> <li> - <a href="Glossary.htm#section0">Container</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm#section0">Container</a> <ul /> </li> <li> - <a href="Glossary.htm#section1">PluginType &amp; PluggedType</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm#section1">PluginType &amp; PluggedType</a> <ul /> </li> <li> - <a href="Glossary.htm#section2">Instance</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm#section2">Instance</a> <ul /> </li> <li> - <a href="Glossary.htm#section3">Scoping (or Lifecycle)</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm#section3">Scoping (or Lifecycle)</a> <ul /> </li> <li> - <a href="Glossary.htm#section4">Profile</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm#section4">Profile</a> <ul /> </li> <li> - <a href="Glossary.htm#section5">Interceptor</a> + <a href="http://structuremap.sourceforge.net/Glossary.htm#section5">Interceptor</a> <ul /> </li> </ul> </li> <li> - <a href="Concepts.htm">Software Design Concepts</a> + <a href="http://structuremap.sourceforge.net/Concepts.htm">Software Design Concepts</a> <ul> <li> - <a href="Concepts.htm#section0">Design Concepts</a> + <a href="http://structuremap.sourceforge.net/Concepts.htm#section0">Design Concepts</a> <ul /> </li> <li> - <a href="Concepts.htm#section1">Dependencies</a> + <a href="http://structuremap.sourceforge.net/Concepts.htm#section1">Dependencies</a> <ul /> </li> <li> - <a href="Concepts.htm#section2">Inversion of Control and Dependency Injection</a> + <a href="http://structuremap.sourceforge.net/Concepts.htm#section2">Inversion of Control and Dependency Injection</a> <ul /> </li> <li> - <a href="Concepts.htm#section3">Auto Wiring</a> + <a href="http://structuremap.sourceforge.net/Concepts.htm#section3">Auto Wiring</a> <ul /> </li> </ul> </li> <li> - <a href="DependencyInjection.htm">Dependency Injection</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm">Dependency Injection</a> <ul> <li> - <a href="DependencyInjection.htm#section0">Dependency Injection</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section0">Dependency Injection</a> <ul /> </li> <li> - <a href="DependencyInjection.htm#section1">Example Problem</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section1">Example Problem</a> <ul /> </li> <li> - <a href="DependencyInjection.htm#section2">Constructor Injection</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section2">Constructor Injection</a> <ul /> </li> <li> - <a href="DependencyInjection.htm#section3">Setter Injection</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section3">Setter Injection</a> <ul /> </li> <li> - <a href="DependencyInjection.htm#section4">Service Locator</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section4">Service Locator</a> <ul /> </li> <li> - <a href="DependencyInjection.htm#section5">Good for More than Unit Testing</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section5">Good for More than Unit Testing</a> <ul /> </li> <li> - <a href="DependencyInjection.htm#section6">Using a Dependency Injection Tool</a> + <a href="http://structuremap.sourceforge.net/DependencyInjection.htm#section6">Using a Dependency Injection Tool</a> <ul /> </li> </ul> </li> <li> - <a href="InversionOfControl.htm">Inversion of Control</a> + <a href="http://structuremap.sourceforge.net/InversionOfControl.htm">Inversion of Control</a> <ul> <li> - <a href="InversionOfControl.htm#section0">Real Life Example</a> + <a href="http://structuremap.sourceforge.net/InversionOfControl.htm#section0">Real Life Example</a> <ul /> </li> <li> - <a href="InversionOfControl.htm#section1">Refactoring to Inversion of Control</a> + <a href="http://structuremap.sourceforge.net/InversionOfControl.htm#section1">Refactoring to Inversion of Control</a> <ul /> </li> <li> - <a href="InversionOfControl.htm#section2">Other Examples</a> + <a href="http://structuremap.sourceforge.net/InversionOfControl.htm#section2">Other Examples</a> <ul /> </li> </ul> </li> <li> - <a href="ConfiguringStructureMap.htm">Configuring StructureMap</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm">Configuring StructureMap</a> <ul> <li> - <a href="ConfiguringStructureMap.htm#section0">Forms of Configuration</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section0">Forms of Configuration</a> <ul /> </li> <li> - <a href="ConfiguringStructureMap.htm#section1">Initializing the Container</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section1">Initializing the Container</a> <ul> <li> - <a href="ConfiguringStructureMap.htm#section2">Using the App.Config File</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section2">Using the App.Config File</a> </li> <li> - <a href="ConfiguringStructureMap.htm#section3">The StructureMap.config File</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section3">The StructureMap.config File</a> </li> </ul> </li> <li> - <a href="ConfiguringStructureMap.htm#section4">Where and How to Bootstrap StructureMap</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section4">Where and How to Bootstrap StructureMap</a> <ul> <li> - <a href="ConfiguringStructureMap.htm#section5">Creating a Bootstrapper</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section5">Creating a Bootstrapper</a> </li> <li> - <a href="ConfiguringStructureMap.htm#section6">StructureMapConfiguration</a> + <a href="http://structuremap.sourceforge.net/ConfiguringStructureMap.htm#section6">StructureMapConfiguration</a> </li> </ul> </li> </ul> </li> <li> - <a href="RegistryDSL.htm">Registry DSL</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm">Registry DSL</a> <ul> <li> - <a href="RegistryDSL.htm#section0">The Registry Class</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section0">The Registry Class</a> <ul> <li> - <a href="RegistryDSL.htm#section1">Applying Registry Classes</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section1">Applying Registry Classes</a> </li> <li> - <a href="RegistryDSL.htm#section2">The Registry DSL Methods</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section2">The Registry DSL Methods</a> </li> </ul> </li> <li> - <a href="RegistryDSL.htm#section3">Registering Types</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section3">Registering Types</a> <ul> <li> - <a href="RegistryDSL.htm#section4">Specifying the Default Instance for a PluginType</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section4">Specifying the Default Instance for a PluginType</a> </li> <li> - <a href="RegistryDSL.htm#section5">Specifying Additional Instances for a PluginType</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section5">Specifying Additional Instances for a PluginType</a> </li> <li> - <a href="RegistryDSL.htm#section6">Setting the Scoping/Lifecycle for a PluginType</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section6">Setting the Scoping/Lifecycle for a PluginType</a> </li> </ul> </li> <li> - <a href="RegistryDSL.htm#section7">Registering a "Missing Instance"</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section7">Registering a "Missing Instance"</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section8">Configuring Concrete Types</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section8">Configuring Concrete Types</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section9">Working with Open Generic Types</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section9">Working with Open Generic Types</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section10">Auto Registration and Assembly ScanningScanning</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section10">Auto Registration and Assembly ScanningScanning</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section11">Setter Injection Policies</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section11">Setter Injection Policies</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section12">Interception</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section12">Interception</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section13">Creating a Profile</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section13">Creating a Profile</a> <ul /> </li> <li> - <a href="RegistryDSL.htm#section14">Using the Registry DSL Directly in Initializationlization</a> + <a href="http://structuremap.sourceforge.net/RegistryDSL.htm#section14">Using the Registry DSL Directly in Initializationlization</a> <ul /> </li> </ul> </li> <li> - <a href="InstanceExpression.htm">Configuring Instances</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm">Configuring Instances</a> <ul> <li> - <a href="InstanceExpression.htm#section0">Instance Expression</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section0">Instance Expression</a> <ul> <li> - <a href="InstanceExpression.htm#section1">InstanceExpression Operations</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section1">InstanceExpression Operations</a> </li> </ul> </li> <li> - <a href="InstanceExpression.htm#section2">Building with Constructors and Setters</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section2">Building with Constructors and Setters</a> <ul> <li> - <a href="InstanceExpression.htm#section3">Designating the Type</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section3">Designating the Type</a> </li> <li> - <a href="InstanceExpression.htm#section4">Defining primitive constructor arguments</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section4">Defining primitive constructor arguments</a> </li> <li> - <a href="InstanceExpression.htm#section5">Defining primitive setter properties</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section5">Defining primitive setter properties</a> </li> <li> - <a href="InstanceExpression.htm#section6">Overriding Constructor Dependencies</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section6">Overriding Constructor Dependencies</a> </li> <li> - <a href="InstanceExpression.htm#section7">Overriding Setter Dependencies</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section7">Overriding Setter Dependencies</a> </li> <li> - <a href="InstanceExpression.htm#section8">Array or Non Primitive Dependencies</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section8">Array or Non Primitive Dependencies</a> </li> <li> - <a href="InstanceExpression.htm#section9">Primitive Arrays and Dictionaries</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section9">Primitive Arrays and Dictionaries</a> </li> </ul> </li> <li> - <a href="InstanceExpression.htm#section10">Using a Custom Instance</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section10">Using a Custom Instance</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section11">Using an Externally Constructed Object</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section11">Using an Externally Constructed Object</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section12">Constructing Objects with Lambda Functions</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section12">Constructing Objects with Lambda Functions</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section13">Referencing a Named Instance</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section13">Referencing a Named Instance</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section14">Using the Default Instance</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section14">Using the Default Instance</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section15">Specifying a Prototype Object with Cloning</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section15">Specifying a Prototype Object with Cloning</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section16">Specifying a Prototype Object with Serialization</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section16">Specifying a Prototype Object with Serialization</a> <ul /> </li> <li> - <a href="InstanceExpression.htm#section17">Configuring Conditional Construction</a> + <a href="http://structuremap.sourceforge.net/InstanceExpression.htm#section17">Configuring Conditional Construction</a> <ul /> </li> </ul> </li> <li> - <a href="XmlConfiguration.htm">Xml Configuration</a> + <a href="http://structuremap.sourceforge.net/XmlConfiguration.htm">Xml Configuration</a> <ul> <li> - <a href="XmlConfiguration.htm#section0">&lt;StructureMap&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlConfiguration.htm#section0">&lt;StructureMap&gt; Element</a> <ul> <li> - <a href="XmlConfiguration.htm#section1">Configuring Instances</a> + <a href="http://structuremap.sourceforge.net/XmlConfiguration.htm#section1">Configuring Instances</a> </li> </ul> </li> <li> - <a href="XmlConfiguration.htm#section2">Adding a Default Instance for a PluginType</a> + <a href="http://structuremap.sourceforge.net/XmlConfiguration.htm#section2">Adding a Default Instance for a PluginType</a> <ul /> </li> <li> - <a href="XmlConfiguration.htm#section3">Adding Additional Instances for a PluginType</a> + <a href="http://structuremap.sourceforge.net/XmlConfiguration.htm#section3">Adding Additional Instances for a PluginType</a> <ul /> </li> <li> - <a href="XmlConfiguration.htm#section4">Defining a Profile</a> + <a href="http://structuremap.sourceforge.net/XmlConfiguration.htm#section4">Defining a Profile</a> <ul /> </li> </ul> </li> <li> - <a href="XmlReference.htm">Xml Reference</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm">Xml Reference</a> <ul> <li> - <a href="XmlReference.htm#section0">&lt;StructureMap&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section0">&lt;StructureMap&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section1">&lt;Include&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section1">&lt;Include&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section2">&lt;Assembly&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section2">&lt;Assembly&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section3">&lt;Instances&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section3">&lt;Instances&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section4">&lt;Machine&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section4">&lt;Machine&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section5">&lt;PluginFamily&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section5">&lt;PluginFamily&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section6">&lt;DefaultInstance&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section6">&lt;DefaultInstance&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section7">&lt;Profile&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section7">&lt;Profile&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section8">&lt;Instance&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section8">&lt;Instance&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section9">&lt;Interceptors&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section9">&lt;Interceptors&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section10">&lt;Interceptor&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section10">&lt;Interceptor&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section11">&lt;Override&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section11">&lt;Override&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section12">&lt;Plugin&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section12">&lt;Plugin&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section13">&lt;Setter&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section13">&lt;Setter&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section14">&lt;Source&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section14">&lt;Source&gt; Element</a> <ul /> </li> <li> - <a href="XmlReference.htm#section15">&lt;Property&gt; Element</a> + <a href="http://structuremap.sourceforge.net/XmlReference.htm#section15">&lt;Property&gt; Element</a> <ul /> </li> </ul> </li> <li> - <a href="NodeNormalized.htm">Node Normalized Instances</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm">Node Normalized Instances</a> <ul> <li> - <a href="NodeNormalized.htm#section0">Instance Root Node</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section0">Instance Root Node</a> <ul /> </li> <li> - <a href="NodeNormalized.htm#section1">Primitive Properties (Strings and basic value types)</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section1">Primitive Properties (Strings and basic value types)</a> <ul /> </li> <li> - <a href="NodeNormalized.htm#section2">Long Strings</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section2">Long Strings</a> <ul /> </li> <li> - <a href="NodeNormalized.htm#section3">Enumeration Properties</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section3">Enumeration Properties</a> <ul /> </li> <li> - <a href="NodeNormalized.htm#section4">Dependency Properties</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section4">Dependency Properties</a> <ul> <li> - <a href="NodeNormalized.htm#section5">Inline Definition</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section5">Inline Definition</a> </li> <li> - <a href="NodeNormalized.htm#section6">Reference Definition</a> + <a href="http://structuremap.sourceforge.net/NodeNormalized.htm#section6">Reference Definition</a> </li> </ul> </li> </ul> </li> <li> - <a href="AttributeNormalized.htm">Attribute Normalized Instances</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm">Attribute Normalized Instances</a> <ul> <li> - <a href="AttributeNormalized.htm#section0">Instance Root Node</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section0">Instance Root Node</a> <ul /> </li> <li> - <a href="AttributeNormalized.htm#section1">Primitive Properties (Strings and basic value types)</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section1">Primitive Properties (Strings and basic value types)</a> <ul /> </li> <li> - <a href="AttributeNormalized.htm#section2">Long Strings</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section2">Long Strings</a> <ul /> </li> <li> - <a href="AttributeNormalized.htm#section3">Enumeration Properties</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section3">Enumeration Properties</a> <ul /> </li> <li> - <a href="AttributeNormalized.htm#section4">Dependency Properties</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section4">Dependency Properties</a> <ul> <li> - <a href="AttributeNormalized.htm#section5">Inline Definition</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section5">Inline Definition</a> </li> <li> - <a href="AttributeNormalized.htm#section6">Reference Definition</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section6">Reference Definition</a> </li> </ul> </li> <li> - <a href="AttributeNormalized.htm#section7">Non Primitive Array Property</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section7">Non Primitive Array Property</a> <ul /> </li> <li> - <a href="AttributeNormalized.htm#section8">Primitive Arrays</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section8">Primitive Arrays</a> <ul /> </li> <li> - <a href="AttributeNormalized.htm#section9">Dictionaries and NameValueCollection</a> + <a href="http://structuremap.sourceforge.net/AttributeNormalized.htm#section9">Dictionaries and NameValueCollection</a> <ul /> </li> </ul> </li> <li> - <a href="ScanningAssemblies.htm">Auto Registration and Type Scanning</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm">Auto Registration and Type Scanning</a> <ul> <li> - <a href="ScanningAssemblies.htm#section0">Using the Scan() Expression</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section0">Using the Scan() Expression</a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section1">Rules for Auto Registering a Type</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section1">Rules for Auto Registering a Type</a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section2">Designating Assemblies </a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section2">Designating Assemblies </a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section3">Scan all Assemblies in a Given Folder</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section3">Scan all Assemblies in a Given Folder</a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section4">Add All Concrete Types for a PluginType</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section4">Add All Concrete Types for a PluginType</a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section5">Excluding or Including Types</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section5">Excluding or Including Types</a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section6">Type Scanning with Attributes</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section6">Type Scanning with Attributes</a> <ul /> </li> <li> - <a href="ScanningAssemblies.htm#section7">Convention Based Type Registration</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section7">Convention Based Type Registration</a> <ul> <li> - <a href="ScanningAssemblies.htm#section8">The Default Convention</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section8">The Default Convention</a> </li> <li> - <a href="ScanningAssemblies.htm#section9">Registering Types by Name</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section9">Registering Types by Name</a> </li> <li> - <a href="ScanningAssemblies.htm#section10">Creating and Using Your Own Convention</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section10">Creating and Using Your Own Convention</a> </li> </ul> </li> <li> - <a href="ScanningAssemblies.htm#section11">Looking for Registries</a> + <a href="http://structuremap.sourceforge.net/ScanningAssemblies.htm#section11">Looking for Registries</a> <ul /> </li> </ul> </li> <li> - <a href="Scoping.htm">Scoping, Caching, and Lifecycle Management</a> + <a href="http://structuremap.sourceforge.net/Scoping.htm">Scoping, Caching, and Lifecycle Management</a> <ul> <li> - <a href="Scoping.htm#section0">Setting the Scope in the Registry DSL</a> + <a href="http://structuremap.sourceforge.net/Scoping.htm#section0">Setting the Scope in the Registry DSL</a> <ul /> </li> <li> - <a href="Scoping.htm#section1">Setting the Scope in the Xml Configuration</a> + <a href="http://structuremap.sourceforge.net/Scoping.htm#section1">Setting the Scope in the Xml Configuration</a> <ul /> </li> <li> - <a href="Scoping.htm#section2">Setting the Scope with the PluginFamily Attribute</a> + <a href="http://structuremap.sourceforge.net/Scoping.htm#section2">Setting the Scope with the PluginFamily Attribute</a> <ul /> </li> <li> - <a href="Scoping.htm#section3">Using a Custom Scope/Lifecycle</a> + <a href="http://structuremap.sourceforge.net/Scoping.htm#section3">Using a Custom Scope/Lifecycle</a> <ul /> </li> </ul> </li> <li> - <a href="UsingAttributes.htm">Using Attributes</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm">Using Attributes</a> <ul> <li> - <a href="UsingAttributes.htm#section0">Scanning for Classes marked with Attributes</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm#section0">Scanning for Classes marked with Attributes</a> <ul /> </li> <li> - <a href="UsingAttributes.htm#section1">[DefaultConstructor] Attribute</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm#section1">[DefaultConstructor] Attribute</a> <ul /> </li> <li> - <a href="UsingAttributes.htm#section2">[PluginFamily] Attribute</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm#section2">[PluginFamily] Attribute</a> <ul /> </li> <li> - <a href="UsingAttributes.htm#section3">[Pluggable] Attribute</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm#section3">[Pluggable] Attribute</a> <ul /> </li> <li> - <a href="UsingAttributes.htm#section4">[SetterProperty] Attribute</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm#section4">[SetterProperty] Attribute</a> <ul /> </li> <li> - <a href="UsingAttributes.htm#section5">[ValidationMethod] Attribute</a> + <a href="http://structuremap.sourceforge.net/UsingAttributes.htm#section5">[ValidationMethod] Attribute</a> <ul /> </li> </ul> </li> <li> - <a href="Profiles.htm">Profiles</a> + <a href="http://structuremap.sourceforge.net/Profiles.htm">Profiles</a> <ul /> </li> <li> - <a href="Interception.htm">Interception</a> + <a href="http://structuremap.sourceforge.net/Interception.htm">Interception</a> <ul> <li> - <a href="Interception.htm#section0">Intercept a Single Instance</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section0">Intercept a Single Instance</a> <ul> <li> - <a href="Interception.htm#section1">Run an Action Against an Object</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section1">Run an Action Against an Object</a> </li> <li> - <a href="Interception.htm#section2">Wrap or Substitute the Returned Object</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section2">Wrap or Substitute the Returned Object</a> </li> <li> - <a href="Interception.htm#section3">With a Custom Interceptor</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section3">With a Custom Interceptor</a> </li> </ul> </li> <li> - <a href="Interception.htm#section4">Apply Interception to all Instances of a PluginType</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section4">Apply Interception to all Instances of a PluginType</a> <ul /> </li> <li> - <a href="Interception.htm#section5">Apply Interception to all Types Matching a Criteria</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section5">Apply Interception to all Types Matching a Criteria</a> <ul /> </li> <li> - <a href="Interception.htm#section6">Creating a Custom Type Interceptor</a> + <a href="http://structuremap.sourceforge.net/Interception.htm#section6">Creating a Custom Type Interceptor</a> <ul /> </li> </ul> </li> <li> - <a href="ChangingConfigurationAtRuntime.htm">Changing Configuration at Runtime</a> + <a href="http://structuremap.sourceforge.net/ChangingConfigurationAtRuntime.htm">Changing Configuration at Runtime</a> <ul> <li> - <a href="ChangingConfigurationAtRuntime.htm#section0">Adding Configuration to an Existing Container</a> + <a href="http://structuremap.sourceforge.net/ChangingConfigurationAtRuntime.htm#section0">Adding Configuration to an Existing Container</a> <ul /> </li> <li> - <a href="ChangingConfigurationAtRuntime.htm#section1">Injecting a Single Service at Runtime</a> + <a href="http://structuremap.sourceforge.net/ChangingConfigurationAtRuntime.htm#section1">Injecting a Single Service at Runtime</a> <ul /> </li> <li> - <a href="ChangingConfigurationAtRuntime.htm#section2">Injecting a Mock or a Stub at Runtime</a> + <a href="http://structuremap.sourceforge.net/ChangingConfigurationAtRuntime.htm#section2">Injecting a Mock or a Stub at Runtime</a> <ul /> </li> <li> - <a href="ChangingConfigurationAtRuntime.htm#section3">Ejecting all Instances of a PluginType</a> + <a href="http://structuremap.sourceforge.net/ChangingConfigurationAtRuntime.htm#section3">Ejecting all Instances of a PluginType</a> <ul /> </li> </ul> </li> <li> - <a href="RetrievingServices.htm">Retrieving Services</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm">Retrieving Services</a> <ul> <li> - <a href="RetrievingServices.htm#section0">Get a Service by PluginType</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm#section0">Get a Service by PluginType</a> <ul /> </li> <li> - <a href="RetrievingServices.htm#section1">Get a Service by PluginType and Name</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm#section1">Get a Service by PluginType and Name</a> <ul /> </li> <li> - <a href="RetrievingServices.htm#section2">Get all Instances of a PluginType</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm#section2">Get all Instances of a PluginType</a> <ul /> </li> <li> - <a href="RetrievingServices.htm#section3">"Fill" all of the Dependencies of a Concrete Class</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm#section3">"Fill" all of the Dependencies of a Concrete Class</a> <ul /> </li> <li> - <a href="RetrievingServices.htm#section4">Passing Arguments to StructureMap at Runtime</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm#section4">Passing Arguments to StructureMap at Runtime</a> <ul /> </li> <li> - <a href="RetrievingServices.htm#section5">"Try" to Get an Instance</a> + <a href="http://structuremap.sourceforge.net/RetrievingServices.htm#section5">"Try" to Get an Instance</a> <ul /> </li> </ul> </li> <li> - <a href="AutoMocker.htm">Using the StructureMap AutoMocker</a> + <a href="http://structuremap.sourceforge.net/AutoMocker.htm">Using the StructureMap AutoMocker</a> <ul> <li> - <a href="AutoMocker.htm#section0">How it Works</a> + <a href="http://structuremap.sourceforge.net/AutoMocker.htm#section0">How it Works</a> <ul /> </li> <li> - <a href="AutoMocker.htm#section1">How it uses Mock Engines</a> + <a href="http://structuremap.sourceforge.net/AutoMocker.htm#section1">How it uses Mock Engines</a> <ul /> </li> <li> - <a href="AutoMocker.htm#section2">Supplying Mocks or Stubs to the AutoMocker</a> + <a href="http://structuremap.sourceforge.net/AutoMocker.htm#section2">Supplying Mocks or Stubs to the AutoMocker</a> <ul /> </li> <li> - <a href="AutoMocker.htm#section3">Partial Mock the ClassUnderTest</a> + <a href="http://structuremap.sourceforge.net/AutoMocker.htm#section3">Partial Mock the ClassUnderTest</a> <ul /> </li> </ul> </li> <li> - <a href="Diagnostics.htm">Diagnostics and Environment Tests</a> + <a href="http://structuremap.sourceforge.net/Diagnostics.htm">Diagnostics and Environment Tests</a> <ul> <li> - <a href="Diagnostics.htm#section0">What do I Have?</a> + <a href="http://structuremap.sourceforge.net/Diagnostics.htm#section0">What do I Have?</a> <ul /> </li> <li> - <a href="Diagnostics.htm#section1">Asserting that Configuration is Valid</a> + <a href="http://structuremap.sourceforge.net/Diagnostics.htm#section1">Asserting that Configuration is Valid</a> <ul /> </li> <li> - <a href="Diagnostics.htm#section2">Environment Tests</a> + <a href="http://structuremap.sourceforge.net/Diagnostics.htm#section2">Environment Tests</a> <ul /> </li> <li> - <a href="Diagnostics.htm#section3">StructureMapDoctor</a> + <a href="http://structuremap.sourceforge.net/Diagnostics.htm#section3">StructureMapDoctor</a> <ul /> </li> <li> - <a href="Diagnostics.htm#section4">Querying the Configuration</a> + <a href="http://structuremap.sourceforge.net/Diagnostics.htm#section4">Querying the Configuration</a> <ul /> </li> </ul> </li> <li> - <a href="HowDoesStructureMapWork.htm">How does StructureMap Wo... [truncated message content] |
From: <us...@us...> - 2009-01-15 16:02:44
|
Revision: 223 http://structuremap.svn.sourceforge.net/structuremap/?rev=223&view=rev Author: ussherm Date: 2009-01-15 16:02:34 +0000 (Thu, 15 Jan 2009) Log Message: ----------- fixing a few typos Modified Paths: -------------- trunk/Source/HTML/UsingSessionContext.htm Modified: trunk/Source/HTML/UsingSessionContext.htm =================================================================== --- trunk/Source/HTML/UsingSessionContext.htm 2009-01-14 16:48:11 UTC (rev 222) +++ trunk/Source/HTML/UsingSessionContext.htm 2009-01-15 16:02:34 UTC (rev 223) @@ -382,8 +382,8 @@ View's within any type of desktop application or any kind of NHibernate object where the state or identity of the object requested is important.</p> <p>My team uses this functionality in our NHibernate bootstrapping. We have an - interface named ISessionSource tht is responsible for creating the NHibernate - ISession objects (it wraps a Sessio).</p> + interface named ISessionSource that is responsible for creating the NHibernate + ISession objects (it wraps a Session).</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 ISessionSource\par ??\cf0 \{\par ?? \cf4 PersistenceModel\cf0 Model \{ \cf3 get\cf0 ; \}\par ?? \cf4 ISession\cf0 CreateSession();\par ?? \cf3 void\cf0 BuildSchema();\par ?? \}} --> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fli...@us...> - 2009-01-14 16:48:17
|
Revision: 222 http://structuremap.svn.sourceforge.net/structuremap/?rev=222&view=rev Author: flimflan Date: 2009-01-14 16:48:11 +0000 (Wed, 14 Jan 2009) Log Message: ----------- Applied patch by James Willock to fix the HTTP Session instance scope Modified Paths: -------------- trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs Modified: trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs 2009-01-12 03:30:55 UTC (rev 221) +++ trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs 2009-01-14 16:48:11 UTC (rev 222) @@ -72,12 +72,12 @@ public void CopyTo(Array array, int index) { - throw new NotImplementedException(); + _session.CopyTo(array, index); } public int Count { - get { throw new NotImplementedException(); } + get { return _session.Count; } } public object SyncRoot @@ -87,7 +87,7 @@ public bool IsSynchronized { - get { throw new NotImplementedException(); } + get { return _session.IsSynchronized; } } public bool Contains(object key) @@ -102,7 +102,7 @@ public void Clear() { - throw new NotImplementedException(); + _session.Clear(); } public IDictionaryEnumerator GetEnumerator() @@ -112,18 +112,18 @@ public void Remove(object key) { - throw new NotImplementedException(); + _session.Remove(key.ToString()); } public object this[object key] { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } + get { return _session[key.ToString()]; } + set { _session[key.ToString()] = value; } } public ICollection Keys { - get { throw new NotImplementedException(); } + get { return _session.Keys; } } public ICollection Values @@ -133,7 +133,7 @@ public bool IsReadOnly { - get { throw new NotImplementedException(); } + get { return _session.IsReadOnly; } } public bool IsFixedSize @@ -143,4 +143,4 @@ #endregion } -} \ No newline at end of file +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2009-01-12 03:30:57
|
Revision: 221 http://structuremap.svn.sourceforge.net/structuremap/?rev=221&view=rev Author: jeremydmiller Date: 2009-01-12 03:30:55 +0000 (Mon, 12 Jan 2009) Log Message: ----------- The 2.5.2 release Added Paths: ----------- branches/2.5.2/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2009-01-12 03:29:39
|
Revision: 220 http://structuremap.svn.sourceforge.net/structuremap/?rev=220&view=rev Author: jeremydmiller Date: 2009-01-12 03:29:13 +0000 (Mon, 12 Jan 2009) Log Message: ----------- The final check in for 2.5.2 Modified Paths: -------------- trunk/Source/HTML/AutoMocker.htm trunk/Source/HTML/DependencyInjection.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/InversionOfControl.htm trunk/Source/HTML/Menu.htm trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap.AutoMocking/AutoMocker.cs trunk/Source/StructureMap.Testing/AutoMocking/RhinoAutoMockerTester.cs trunk/Source/StructureMap.sln Added Paths: ----------- trunk/Source/HTML/StructureMap.chm trunk/Source/HTML/TableOfContents.htm trunk/Source/HTML/ToC-Bullet-List.xml trunk/Source/TableOfContentsBuilder/ trunk/Source/TableOfContentsBuilder/Program.cs trunk/Source/TableOfContentsBuilder/Properties/ trunk/Source/TableOfContentsBuilder/Properties/AssemblyInfo.cs trunk/Source/TableOfContentsBuilder/TableOfContentsBuilder.csproj trunk/Source/TableOfContentsBuilder/XmlExtensions.cs trunk/bin/Watin/ trunk/bin/Watin/Interop.SHDocVw.dll trunk/bin/Watin/WatiN.Core.dll Modified: trunk/Source/HTML/AutoMocker.htm =================================================================== --- trunk/Source/HTML/AutoMocker.htm 2009-01-11 22:43:11 UTC (rev 219) +++ trunk/Source/HTML/AutoMocker.htm 2009-01-12 03:29:13 UTC (rev 220) @@ -7,6 +7,385 @@ <script type="text/javascript" src="structuremap.js"></script> </head> <body> - Forthcoming... ETA: 1st Qtr 2009 + <p>StructureMap includes an + <a href="http://blog.eleutian.com/CommentView,guid,762249da-e25a-4503-8f20-c6d59b1a69bc.aspx"> + Auto Mocking Container</a> (a couple actually). If you're not familiar + with the concept, an Auto Mocking Container repurposes an IoC container to + automate the creation and attachment of mock objects to a concrete class within + unit tests. The key fact about any auto mocking container is that it + reduces the mechanical cost of creating + <a href="http://codebetter.com/blogs/jeremy.miller/pages/129544.aspx"> + interaction tests</a> by obviating the need to create mock objects by hand, + track those mock objects in the test, and apply the mocks to a concrete class. + Out of the box, StructureMap includes the RhinoAutoMocker for + <a href="http://ayende.com/projects/rhino-mocks.aspx">RhinoMocks</a> and + MoqAutoMocker for <a href="http://code.google.com/p/moq/">Moq</a>. The + Auto Mocking support is in the StructureMap.AutoMocking.dll.</p> + <p> </p> + + <h2>How it Works</h2> + <p>Let's start with an example from the unit tests. Let's say that you have a + class named "ConcreteClass" that uses three other types of services to perform + its responsibilities.</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 ConcreteClass(\cf4 IMockedService\cf0 service, \cf4 IMockedService2\cf0 service2, \cf4 IMockedService3\cf0 service3)\par ?? \{\par ?? _service = service;\par ?? _service2 = service2;\par ?? _service3 = service3;\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> ConcreteClass(<span style="color: #2b91af;">IMockedService</span> + service, <span style="color: #2b91af;">IMockedService2</span> service2, + <span style="color: #2b91af;">IMockedService3</span> service3)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + _service = service;</p> + <p style="margin: 0px;"> + + _service2 = service2;</p> + <p style="margin: 0px;"> + + _service3 = service3;</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Traditionally, I might write integration tests against ConcreteClass by creating + a different mock object for each service dependency, attach each in the + constructor function of ConcreteClass, and probably track each mock object in a + field of the unit test fixture. With the auto mocking container, it's + simpler:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 // This sets up a Rhino Auto Mocker in the Arrange, Act, Assert mode\par ??\cf0 \cf4 var\cf0 autoMocker = \cf4 new\cf0 \cf5 RhinoAutoMocker\cf0 <\cf5 ConcreteClass\cf0 >(\cf5 MockMode\cf0 .AAA);} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // This sets up a Rhino Auto Mocker in the Arrange, Act, Assert mode</span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> autoMocker = <span style="color: blue;">new</span> + <span style="color: #2b91af;">RhinoAutoMocker</span><<span + style="color: #2b91af;">ConcreteClass</span>>(<span style="color: #2b91af;">MockMode</span>.AAA);</p> + </div> +<!--EndFragment--> +<p>That's the entire mock object setup. To get an instance of the + ConcreteClass inside the unit test you access the ClassUnderTest property of the + auto mocker:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red43\green145\blue175;}??\fs20 \cf3 // Act in the test\par ??\cf0 \cf4 ConcreteClass\cf0 @class = autoMocker.ClassUnderTest;\par ?? @class.CallService();} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Act in the test</span></p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + ConcreteClass</span> @class = autoMocker.ClassUnderTest;</p> + <p style="margin: 0px;"> + @class.CallService();</p> + </div> +<!--EndFragment--> +<p>At the first call to the RhinoAutoMocker.ClassUnderTest, the RhinoAutoMocker:</p> + <ol> + <li> Looked at ConcreteClass</li> + <li>Saw that the greediest constructor required instances of three different + dependencies</li> + <li>Created mock objects using the RhinoMocks MockRepository.CreateMock<T>() method + for each type of dependency</li> + <li>Then called the constructor function of ConcreteClass to build a new instance</li> + </ol> + <p> + ClassUnderTest is created upon demand. Likewise, you can access the actual + mock objects either to set expectations before ClassUnderTest is created, or to + assert method calls after the action. Use the Get<T>() method to access + the mock objects per type that will be used in the test:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red43\green145\blue175;}??\fs20 \cf3 // This retrieves the mock object for IMockedService\par ??\cf0 autoMocker.Get<\cf4 IMockedService\cf0 >().AssertWasCalled(s => s.Go());} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // This retrieves the mock object for IMockedService</span></p> + <p style="margin: 0px;"> + autoMocker.Get<<span + style="color: #2b91af;">IMockedService</span>>().AssertWasCalled(s => + s.Go());</p> + </div> +<!--EndFragment--> +<hr /> + + <h2>How it uses Mock Engines</h2> + <p>If you wanted to use the AutoMocker with another type of Mock Object Library, you + can simply use the AutoMocker<CLASSUNDERTEST> class, but feed it an + implementation of this interface that works with the mock object library of your + choice:</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 ServiceLocator\par ??\cf0 \{\par ?? T Service<T>() \cf3 where\cf0 T : \cf3 class\cf0 ;\par ?? \cf3 object\cf0 Service(\cf4 Type\cf0 serviceType);\par ?? T PartialMock<T>(\cf3 params\cf0 \cf3 object\cf0 [] args) \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;"> + <span style="color: blue;">public</span> <span style="color: blue;">interface</span> + <span style="color: #2b91af;">ServiceLocator</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + T Service<T>() <span style="color: blue;">where</span> + T : <span style="color: blue;">class</span>;</p> + <p style="margin: 0px;"> + <span style="color: blue;">object</span> Service(<span + style="color: #2b91af;">Type</span> serviceType);</p> + <p style="margin: 0px;"> + T PartialMock<T>(<span style="color: blue;">params</span> + <span style="color: blue;">object</span>[] args) <span style="color: blue;"> + where</span> T : <span style="color: blue;">class</span>;</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>The RhinoMocks "AAA" mode 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;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 RhinoMocksAAAServiceLocator\cf0 : \cf4 ServiceLocator\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 RhinoMockRepositoryProxy\cf0 _mocks = \cf3 new\cf0 \cf4 RhinoMockRepositoryProxy\cf0 ();\par ??\par ?? \cf3 public\cf0 T Service<T>() \cf3 where\cf0 T : \cf3 class\par ??\cf0 \{\par ?? \cf3 var\cf0 instance = (T)_mocks.DynamicMock(\cf3 typeof\cf0 (T));\par ?? _mocks.Replay(instance);\par ?? \cf3 return\cf0 instance;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 object\cf0 Service(\cf4 Type\cf0 serviceType)\par ?? \{\par ?? \cf3 var\cf0 instance = _mocks.DynamicMock(serviceType);\par ?? _mocks.Replay(instance);\par ?? \cf3 return\cf0 instance;\par ?? \}\par ??\par ?? \cf3 public\cf0 T PartialMock<T>(\cf3 params\cf0 \cf3 object\cf0 [] args) \cf3 where\cf0 T : \cf3 class\par ??\cf0 \{\par ?? \cf3 var\cf0 instance = (T)_mocks.PartialMock(\cf3 typeof\cf0 (T), args);\par ?? _mocks.Replay(instance);\par ?? \cf3 return\cf0 instance;\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;">RhinoMocksAAAServiceLocator</span> : + <span style="color: #2b91af;">ServiceLocator</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;"> + RhinoMockRepositoryProxy</span> _mocks = <span style="color: blue;">new</span> + <span style="color: #2b91af;">RhinoMockRepositoryProxy</span>();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> T + Service<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: blue;"> + var</span> instance = (T)_mocks.DynamicMock(<span style="color: blue;">typeof</span> + (T));</p> + <p style="margin: 0px;"> + _mocks.Replay(instance);</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> instance;</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;">object</span> Service(<span style="color: #2b91af;">Type</span> + serviceType)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> instance = _mocks.DynamicMock(serviceType);</p> + <p style="margin: 0px;"> + _mocks.Replay(instance);</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> instance;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> T + PartialMock<T>(<span style="color: blue;">params</span> + <span style="color: blue;">object</span>[] args) <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: blue;"> + var</span> instance = (T)_mocks.PartialMock(<span style="color: blue;">typeof</span>(T), + args);</p> + <p style="margin: 0px;"> + _mocks.Replay(instance);</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> instance;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>And this is the Moq version:</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 MoqServiceLocator\cf0 : \cf4 ServiceLocator\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 MoqFactory\cf0 _moqs = \cf3 new\cf0 \cf4 MoqFactory\cf0 ();\par ?? \par ?? \cf3 public\cf0 T Service<T>() \cf3 where\cf0 T : \cf3 class\par ??\cf0 \{\par ?? \cf3 return\cf0 (T)_moqs.CreateMock(\cf3 typeof\cf0 (T));\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 object\cf0 Service(\cf4 Type\cf0 serviceType)\par ?? \{\par ?? \cf3 return\cf0 _moqs.CreateMock(serviceType);\par ?? \}\par ??\par ?? \cf3 public\cf0 T PartialMock<T>(\cf3 params\cf0 \cf3 object\cf0 [] args) \cf3 where\cf0 T : \cf3 class\par ??\cf0 \{\par ?? \cf3 return\cf0 (T)_moqs.CreateMockThatCallsBase(\cf3 typeof\cf0 (T), args);\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;">MoqServiceLocator</span> : + <span style="color: #2b91af;">ServiceLocator</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;"> + MoqFactory</span> _moqs = <span style="color: blue;">new</span> + <span style="color: #2b91af;">MoqFactory</span>();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> T + Service<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: blue;"> + return</span> (T)_moqs.CreateMock(<span style="color: blue;">typeof</span>(T));</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;">object</span> Service(<span style="color: #2b91af;">Type</span> + serviceType)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> _moqs.CreateMock(serviceType);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> T + PartialMock<T>(<span style="color: blue;">params</span> + <span style="color: blue;">object</span>[] args) <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: blue;"> + return</span> (T)_moqs.CreateMockThatCallsBase(<span style="color: blue;">typeof</span> + (T), args);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> + + <h2>Supplying Mocks or Stubs to the AutoMocker</h2> + <p>Frequently you may want to use the AutoMocker, but override the normal mock + object creation with your own stub or hand rolled mock objects. That's + easy enough with the Inject() methods:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 ///\cf4 \cf3 <summary>\par ??\cf0 \cf3 ///\cf4 Method to specify the exact object that will be used for \par ??\cf0 \cf3 ///\cf4 "pluginType." Useful for stub objects and/or static mocks\par ??\cf0 \cf3 ///\cf4 \cf3 </summary>\par ??\cf0 \cf3 ///\cf4 \cf3 <param name="pluginType"></param>\par ??\cf0 \cf3 ///\cf4 \cf3 <param name="stub"></param>\par ??\cf0 \cf5 void\cf0 Inject(\cf6 Type\cf0 pluginType, \cf5 object\cf0 stub);\par ??\par ?? \cf3 ///\cf4 \cf3 <summary>\par ??\cf0 \cf3 ///\cf4 Method to specify the exact object that will be used for \par ??\cf0 \cf3 ///\cf4 "pluginType." Useful for stub objects and/or static mocks\par ??\cf0 \cf3 ///\cf4 \cf3 </summary>\par ??\cf0 \cf3 ///\cf4 \cf3 <typeparam name="T"></typeparam>\par ??\cf0 \cf3 ///\cf4 \cf3 <param name="target"></param>\par ??\cf0 \cf5 void\cf0 Inject<T>(T target);} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> Method to specify the exact object that will be used + for </span> + </p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> "pluginType." Useful for stub objects and/or + static mocks</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"></summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><param + name="pluginType"></param></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><param + name="stub"></param></span></p> + <p style="margin: 0px;"> + <span style="color: blue;">void</span> Inject(<span + style="color: #2b91af;">Type</span> pluginType, <span style="color: blue;"> + object</span> stub);</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;"> Method to specify the exact object that will be used + for </span> + </p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> "pluginType." Useful for stub objects and/or + static mocks</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="target"></param></span></p> + <p style="margin: 0px;"> + <span style="color: blue;">void</span> Inject<T>(T + target);</p> + </div> +<!--EndFragment--> +<hr /> + + <h2>Partial Mock the ClassUnderTest</h2> + <p>Every so often, I find it useful to create a "<a + href="http://ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx">partial mock</a>" + for the ClassUnderTest. That can be done with the AutoMocker by calling + the PartialMockTheClassUnderTest() 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 var\cf0 autoMocker = createAutoMocker<\cf4 ConcreteClass\cf0 >();\par ??\par ?? \cf3 var\cf0 service = autoMocker.Get<\cf4 IMockedService\cf0 >();\par ?? \cf3 var\cf0 service2 = autoMocker.Get<\cf4 IMockedService2\cf0 >();\par ?? \cf3 var\cf0 service3 = autoMocker.Get<\cf4 IMockedService3\cf0 >();\par ??\par ?? autoMocker.PartialMockTheClassUnderTest();} +--> + <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> autoMocker = createAutoMocker<<span style="color: #2b91af;">ConcreteClass</span>>();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> service = autoMocker.Get<<span style="color: #2b91af;">IMockedService</span>>();</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> service2 = autoMocker.Get<<span style="color: #2b91af;">IMockedService2</span>>();</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> service3 = autoMocker.Get<<span style="color: #2b91af;">IMockedService3</span>>();</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + autoMocker.PartialMockTheClassUnderTest();</p> + </div> +<!--EndFragment--> +<p>Expectations and assertions can be made directly on the AutoMocker.ClassUnderTest + property. When the PartialMockTheClassUnderTest() method is called, the + underlying value behind ClassUnderTest will be a partial mock, but the + AutoMocker will still use mock objects for the dependencies of the class under + test.</p> + <hr /> </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/DependencyInjection.htm =================================================================== --- trunk/Source/HTML/DependencyInjection.htm 2009-01-11 22:43:11 UTC (rev 219) +++ trunk/Source/HTML/DependencyInjection.htm 2009-01-12 03:29:13 UTC (rev 220) @@ -22,8 +22,7 @@ still thinks it's much cleaner to use DI ;-)</p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> </p> - <h2 style="margin: 0in 0in 0pt;"> - Dependency Injection</h2> + <h2>Dependency Injection</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> </p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -76,8 +75,7 @@ <hr /> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> - <h2 style="margin: 0in 0in 0pt;"> - <b style="">Example Problem<o:p></o:p></b></h2> + <h2>Example Problem</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -277,8 +275,7 @@ <hr /> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> - <h2 style="margin: 0in 0in 0pt;"> - <b style=""><span class="style1">Constructor Injection</span><o:p></o:p></b></h2> + <h2>Constructor Injection</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -475,8 +472,7 @@ <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <hr /> - <h2 style="margin: 0in 0in 0pt;"> - <b style=""><span class="style1">Setter Injection</span><o:p></o:p></b></h2> + <h2>Setter Injection</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -719,8 +715,7 @@ <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> <hr /> - <h2 style="margin: 0in 0in 0pt;"> - <b style=""><span class="style1">Service Locator</span><o:p></o:p></b></h2> + <h2>Service Locator</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -875,8 +870,7 @@ <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> <hr /> - <h2 style="margin: 0in 0in 0pt;"> - <span style="">Good for More than Unit Testing<o:p></o:p></span></h2> + <h2>Good for More than Unit Testing</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -1034,8 +1028,7 @@ <p class="MsoNormal" style="margin: 0in 0in 0pt;"> </p> <hr /> - <h2 style="margin: 0in 0in 0pt;"> - <span style="">Using a Dependency Injection Tool<o:p></o:p></span></h2> + <h2>Using a Dependency Injection Tool</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> </p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> Modified: trunk/Source/HTML/HTML.csproj =================================================================== --- trunk/Source/HTML/HTML.csproj 2009-01-11 22:43:11 UTC (rev 219) +++ trunk/Source/HTML/HTML.csproj 2009-01-12 03:29:13 UTC (rev 220) @@ -66,6 +66,8 @@ <Content Include="InversionOfControl.htm" /> <Content Include="Profiles.htm" /> <Content Include="Scoping.htm" /> + <Content Include="TableOfContents.htm" /> + <Content Include="ToC-Bullet-List.xml" /> <Content Include="UsingAttributes.htm" /> <Content Include="AutoWiring.htm" /> <Content Include="ConfiguringStructureMap.htm" /> @@ -113,4 +115,7 @@ <Install>false</Install> </BootstrapperPackage> </ItemGroup> + <ItemGroup> + <None Include="StructureMap.chm" /> + </ItemGroup> </Project> \ No newline at end of file Modified: trunk/Source/HTML/InversionOfControl.htm =================================================================== --- trunk/Source/HTML/InversionOfControl.htm 2009-01-11 22:43:11 UTC (rev 219) +++ trunk/Source/HTML/InversionOfControl.htm 2009-01-12 03:29:13 UTC (rev 220) @@ -28,8 +28,7 @@ <o:p> </o:p></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> - <h2 style="margin: 0in 0in 0pt;"> - <b style=""><span class="style1">Real Life Example</span><o:p></o:p></b></h2> + <h2>Real Life Example</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -352,8 +351,7 @@ </ul> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> - <h2 style="margin: 0in 0in 0pt;"> - <b style="">Refactoring to Inversion of Control<o:p></o:p></b></h2> + <h2>Refactoring to Inversion of Control</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> @@ -559,8 +557,7 @@ </p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <o:p> </o:p></p> - <h2 style="margin: 0in 0in 0pt;"> - <b style="">Other Examples<o:p></o:p></b></h2> + <h2>Other Examples</h2> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> <b style=""><o:p> </o:p></b></p> <p class="MsoNormal" style="margin: 0in 0in 0pt;"> Modified: trunk/Source/HTML/Menu.htm =================================================================== --- trunk/Source/HTML/Menu.htm 2009-01-11 22:43:11 UTC (rev 219) +++ trunk/Source/HTML/Menu.htm 2009-01-12 03:29:13 UTC (rev 220) @@ -13,8 +13,9 @@ <li><a href="http://dimecasts.net/Casts/ByTag/StructureMap">StructureMap on DimeCasts</a></li> <li><a href="http://teamcity.codebetter.com/viewType.html?buildTypeId=bt5&tab=buildTypeStatusDiv"> StructureMap CI Server on TeamCity.Codebetter.com</a></li> - <li>Full Table of Contents</li> + <li><a href="TableOfContents.htm">Full Table of Contents</a></li> <li><a href="FeatureList.htm">Feature List</a></li> + <li><a href="StructureMap.chm">API Documentation</a></li> </ul> <br /> <ul> Added: trunk/Source/HTML/StructureMap.chm =================================================================== (Binary files differ) Property changes on: trunk/Source/HTML/StructureMap.chm ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/Source/HTML/TableOfContents.htm =================================================================== --- trunk/Source/HTML/TableOfContents.htm (rev 0) +++ trunk/Source/HTML/TableOfContents.htm 2009-01-12 03:29:13 UTC (rev 220) @@ -0,0 +1,24 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Table of Contents</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> + <script language="javascript"> + $(document).ready(function() { + $.get('ToC-Bullet-List.xml', {}, writeTOC, 'HTML'); + }); + + function writeTOC(data) { + $('#main').html(data); + } + </script> + + <div id="main"> + + </div> + </body> +</html> \ No newline at end of file Added: trunk/Source/HTML/ToC-Bullet-List.xml =================================================================== --- trunk/Source/HTML/ToC-Bullet-List.xml (rev 0) +++ trunk/Source/HTML/ToC-Bullet-List.xml 2009-01-12 03:29:13 UTC (rev 220) @@ -0,0 +1,835 @@ +<div> + <ul> + <li> + <a href="default.htm">Home</a> + <ul> + <li> + <a href="default.htm#section0">Status</a> + <ul /> + </li> + <li> + <a href="default.htm#section1">Related Links:</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="FeatureList.htm">Feature List</a> + <ul /> + </li> + <li> + <a href="QuickStart.htm">A Gentle Quickstart</a> + <ul> + <li> + <a href="QuickStart.htm#section0">Salient Facts</a> + <ul /> + </li> + <li> + <a href="QuickStart.htm#section1">The Simplest Possible Usage of StructureMap</a> + <ul /> + </li> + <li> + <a href="QuickStart.htm#section2">Primitive Arguments</a> + <ul /> + </li> + <li> + <a href="QuickStart.htm#section3">Auto Wiring</a> + <ul /> + </li> + <li> + <a href="QuickStart.htm#section4">What to do when things go wrong?</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="Glossary.htm">Glossary</a> + <ul> + <li> + <a href="Glossary.htm#section0">Container</a> + <ul /> + </li> + <li> + <a href="Glossary.htm#section1">PluginType &amp; PluggedType</a> + <ul /> + </li> + <li> + <a href="Glossary.htm#section2">Instance</a> + <ul /> + </li> + <li> + <a href="Glossary.htm#section3">Scoping (or Lifecycle)</a> + <ul /> + </li> + <li> + <a href="Glossary.htm#section4">Profile</a> + <ul /> + </li> + <li> + <a href="Glossary.htm#section5">Interceptor</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="Concepts.htm">Software Design Concepts</a> + <ul> + <li> + <a href="Concepts.htm#section0">Design Concepts</a> + <ul /> + </li> + <li> + <a href="Concepts.htm#section1">Dependencies</a> + <ul /> + </li> + <li> + <a href="Concepts.htm#section2">Inversion of Control and Dependency Injection</a> + <ul /> + </li> + <li> + <a href="Concepts.htm#section3">Auto Wiring</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="DependencyInjection.htm">Dependency Injection</a> + <ul> + <li> + <a href="DependencyInjection.htm#section0">Dependency Injection</a> + <ul /> + </li> + <li> + <a href="DependencyInjection.htm#section1">Example Problem</a> + <ul /> + </li> + <li> + <a href="DependencyInjection.htm#section2">Constructor Injection</a> + <ul /> + </li> + <li> + <a href="DependencyInjection.htm#section3">Setter Injection</a> + <ul /> + </li> + <li> + <a href="DependencyInjection.htm#section4">Service Locator</a> + <ul /> + </li> + <li> + <a href="DependencyInjection.htm#section5">Good for More than Unit Testing</a> + <ul /> + </li> + <li> + <a href="DependencyInjection.htm#section6">Using a Dependency Injection Tool</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="InversionOfControl.htm">Inversion of Control</a> + <ul> + <li> + <a href="InversionOfControl.htm#section0">Real Life Example</a> + <ul /> + </li> + <li> + <a href="InversionOfControl.htm#section1">Refactoring to Inversion of Control</a> + <ul /> + </li> + <li> + <a href="InversionOfControl.htm#section2">Other Examples</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="ConfiguringStructureMap.htm">Configuring StructureMap</a> + <ul> + <li> + <a href="ConfiguringStructureMap.htm#section0">Forms of Configuration</a> + <ul /> + </li> + <li> + <a href="ConfiguringStructureMap.htm#section1">Initializing the Container</a> + <ul> + <li> + <a href="ConfiguringStructureMap.htm#section2">Using the App.Config File</a> + </li> + <li> + <a href="ConfiguringStructureMap.htm#section3">The StructureMap.config File</a> + </li> + </ul> + </li> + <li> + <a href="ConfiguringStructureMap.htm#section4">Where and How to Bootstrap StructureMap</a> + <ul> + <li> + <a href="ConfiguringStructureMap.htm#section5">Creating a Bootstrapper</a> + </li> + <li> + <a href="ConfiguringStructureMap.htm#section6">StructureMapConfiguration</a> + </li> + </ul> + </li> + </ul> + </li> + <li> + <a href="RegistryDSL.htm">Registry DSL</a> + <ul> + <li> + <a href="RegistryDSL.htm#section0">The Registry Class</a> + <ul> + <li> + <a href="RegistryDSL.htm#section1">Applying Registry Classes</a> + </li> + <li> + <a href="RegistryDSL.htm#section2">The Registry DSL Methods</a> + </li> + </ul> + </li> + <li> + <a href="RegistryDSL.htm#section3">Registering Types</a> + <ul> + <li> + <a href="RegistryDSL.htm#section4">Specifying the Default Instance for a PluginType</a> + </li> + <li> + <a href="RegistryDSL.htm#section5">Specifying Additional Instances for a PluginType</a> + </li> + <li> + <a href="RegistryDSL.htm#section6">Setting the Scoping/Lifecycle for a PluginType</a> + </li> + </ul> + </li> + <li> + <a href="RegistryDSL.htm#section7">Registering a "Missing Instance"</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section8">Configuring Concrete Types</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section9">Working with Open Generic Types</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section10">Auto Registration and Assembly ScanningScanning</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section11">Setter Injection Policies</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section12">Interception</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section13">Creating a Profile</a> + <ul /> + </li> + <li> + <a href="RegistryDSL.htm#section14">Using the Registry DSL Directly in Initializationlization</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="InstanceExpression.htm">Configuring Instances</a> + <ul> + <li> + <a href="InstanceExpression.htm#section0">Instance Expression</a> + <ul> + <li> + <a href="InstanceExpression.htm#section1">InstanceExpression Operations</a> + </li> + </ul> + </li> + <li> + <a href="InstanceExpression.htm#section2">Building with Constructors and Setters</a> + <ul> + <li> + <a href="InstanceExpression.htm#section3">Designating the Type</a> + </li> + <li> + <a href="InstanceExpression.htm#section4">Defining primitive constructor arguments</a> + </li> + <li> + <a href="InstanceExpression.htm#section5">Defining primitive setter properties</a> + </li> + <li> + <a href="InstanceExpression.htm#section6">Overriding Constructor Dependencies</a> + </li> + <li> + <a href="InstanceExpression.htm#section7">Overriding Setter Dependencies</a> + </li> + <li> + <a href="InstanceExpression.htm#section8">Array or Non Primitive Dependencies</a> + </li> + <li> + <a href="InstanceExpression.htm#section9">Primitive Arrays and Dictionaries</a> + </li> + </ul> + </li> + <li> + <a href="InstanceExpression.htm#section10">Using a Custom Instance</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section11">Using an Externally Constructed Object</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section12">Constructing Objects with Lambda Functions</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section13">Referencing a Named Instance</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section14">Using the Default Instance</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section15">Specifying a Prototype Object with Cloning</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section16">Specifying a Prototype Object with Serialization</a> + <ul /> + </li> + <li> + <a href="InstanceExpression.htm#section17">Configuring Conditional Construction</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="XmlConfiguration.htm">Xml Configuration</a> + <ul> + <li> + <a href="XmlConfiguration.htm#section0">&lt;StructureMap&gt; Element</a> + <ul> + <li> + <a href="XmlConfiguration.htm#section1">Configuring Instances</a> + </li> + </ul> + </li> + <li> + <a href="XmlConfiguration.htm#section2">Adding a Default Instance for a PluginType</a> + <ul /> + </li> + <li> + <a href="XmlConfiguration.htm#section3">Adding Additional Instances for a PluginType</a> + <ul /> + </li> + <li> + <a href="XmlConfiguration.htm#section4">Defining a Profile</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="XmlReference.htm">Xml Reference</a> + <ul> + <li> + <a href="XmlReference.htm#section0">&lt;StructureMap&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section1">&lt;Include&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section2">&lt;Assembly&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section3">&lt;Instances&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section4">&lt;Machine&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section5">&lt;PluginFamily&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section6">&lt;DefaultInstance&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section7">&lt;Profile&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section8">&lt;Instance&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section9">&lt;Interceptors&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section10">&lt;Interceptor&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section11">&lt;Override&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section12">&lt;Plugin&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section13">&lt;Setter&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section14">&lt;Source&gt; Element</a> + <ul /> + </li> + <li> + <a href="XmlReference.htm#section15">&lt;Property&gt; Element</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="NodeNormalized.htm">Node Normalized Instances</a> + <ul> + <li> + <a href="NodeNormalized.htm#section0">Instance Root Node</a> + <ul /> + </li> + <li> + <a href="NodeNormalized.htm#section1">Primitive Properties (Strings and basic value types)</a> + <ul /> + </li> + <li> + <a href="NodeNormalized.htm#section2">Long Strings</a> + <ul /> + </li> + <li> + <a href="NodeNormalized.htm#section3">Enumeration Properties</a> + <ul /> + </li> + <li> + <a href="NodeNormalized.htm#section4">Dependency Properties</a> + <ul> + <li> + <a href="NodeNormalized.htm#section5">Inline Definition</a> + </li> + <li> + <a href="NodeNormalized.htm#section6">Reference Definition</a> + </li> + </ul> + </li> + </ul> + </li> + <li> + <a href="AttributeNormalized.htm">Attribute Normalized Instances</a> + <ul> + <li> + <a href="AttributeNormalized.htm#section0">Instance Root Node</a> + <ul /> + </li> + <li> + <a href="AttributeNormalized.htm#section1">Primitive Properties (Strings and basic value types)</a> + <ul /> + </li> + <li> + <a href="AttributeNormalized.htm#section2">Long Strings</a> + <ul /> + </li> + <li> + <a href="AttributeNormalized.htm#section3">Enumeration Properties</a> + <ul /> + </li> + <li> + <a href="AttributeNormalized.htm#section4">Dependency Properties</a> + <ul> + <li> + <a href="AttributeNormalized.htm#section5">Inline Definition</a> + </li> + <li> + <a href="AttributeNormalized.htm#section6">Reference Definition</a> + </li> + </ul> + </li> + <li> + <a href="AttributeNormalized.htm#section7">Non Primitive Array Property</a> + <ul /> + </li> + <li> + <a href="AttributeNormalized.htm#section8">Primitive Arrays</a> + <ul /> + </li> + <li> + <a href="AttributeNormalized.htm#section9">Dictionaries and NameValueCollection</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="ScanningAssemblies.htm">Auto Registration and Type Scanning</a> + <ul> + <li> + <a href="ScanningAssemblies.htm#section0">Using the Scan() Expression</a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section1">Rules for Auto Registering a Type</a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section2">Designating Assemblies </a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section3">Scan all Assemblies in a Given Folder</a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section4">Add All Concrete Types for a PluginType</a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section5">Excluding or Including Types</a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section6">Type Scanning with Attributes</a> + <ul /> + </li> + <li> + <a href="ScanningAssemblies.htm#section7">Convention Based Type Registration</a> + <ul> + <li> + <a href="ScanningAssemblies.htm#section8">The Default Convention</a> + </li> + <li> + <a href="ScanningAssemblies.htm#section9">Registering Types by Name</a> + </li> + <li> + <a href="ScanningAssemblies.htm#section10">Creating and Using Your Own Convention</a> + </li> + </ul> + </li> + <li> + <a href="ScanningAssemblies.htm#section11">Looking for Registries</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="Scoping.htm">Scoping, Caching, and Lifecycle Management</a> + <ul> + <li> + <a href="Scoping.htm#section0">Setting the Scope in the Registry DSL</a> + <ul /> + </li> + <li> + <a href="Scoping.htm#section1">Setting the Scope in the Xml Configuration</a> + <ul /> + </li> + <li> + <a href="Scoping.htm#section2">Setting the Scope with the PluginFamily Attribute</a> + <ul /> + </li> + <li> + <a href="Scoping.htm#section3">Using a Custom Scope/Lifecycle</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="UsingAttributes.htm">Using Attributes</a> + <ul> + <li> + <a href="UsingAttributes.htm#section0">Scanning for Classes marked with Attributes</a> + <ul /> + </li> + <li> + <a href="UsingAttributes.htm#section1">[DefaultConstructor] Attribute</a> + <ul /> + </li> + <li> + <a href="UsingAttributes.htm#section2">[PluginFamily] Attribute</a> + <ul /> + </li> + <li> + <a href="UsingAttributes.htm#section3">[Pluggable] Attribute</a> + <ul /> + </li> + <li> + <a href="UsingAttributes.htm#section4">[SetterProperty] Attribute</a> + <ul /> + </li> + <li> + <a href="UsingAttributes.htm#section5">[ValidationMethod] Attribute</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="Profiles.htm">Profiles</a> + <ul /> + </li> + <li> + <a href="Interception.htm">Interception</a> + <ul> + <li> + <a href="Interception.htm#section0">Intercept a Single Instance</a> + <ul> + <li> + <a href="Interception.htm#section1">Run an Action Against an Object</a> + </li> + <li> + <a href="Interception.htm#section2">Wrap or Substitute the Returned Object</a> + </li> + <li> + <a href="Interception.htm#section3">With a Custom Interceptor</a> + </li> + </ul> + </li> + <li> + <a href="Interception.htm#section4">Apply Interception to all Instances of a PluginType</a> + <ul /> + </li> + <li> + <a href="Interception.htm#section5">Apply Interception to all Types Matching a Criteria</a> + <ul /> + </li> + <li> + <a href="Interception.htm#section6">Creating a Custom Type Interceptor</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="ChangingConfigurationAtRuntime.htm">Changing Configuration at Runtime</a> + <ul> + <li> + <a href="ChangingConfigurationAtRuntime.htm#section0">Adding Configuration to an Existing Container</a> + <ul /> + </li> + <li> + <a href="ChangingConfigurationAtRuntime.htm#section1">Injecting a Single Service at Runtime</a> + <ul /> + </li> + <li> + <a href="ChangingConfigurationAtRuntime.htm#section2">Injecting a Mock or a Stub at Runtime</a> + <ul /> + </li> + <li> + <a href="ChangingConfigurationAtRuntime.htm#section3">Ejecting all Instances of a PluginType</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="RetrievingServices.htm">Retrieving Services</a> + <ul> + <li> + <a href="RetrievingServices.htm#section0">Get a Service by PluginType</a> + <ul /> + </li> + <li> + <a href="RetrievingServices.htm#section1">Get a Service by PluginType and Name</a> + <ul /> + </li> + <li> + <a href="RetrievingServices.htm#section2">Get all Instances of a PluginType</a> + <ul /> + </li> + <li> + <a href="RetrievingServices.htm#section3">"Fill" all of the Dependencies of a Concrete Class</a> + <ul /> + </li> + <li> + <a href="RetrievingServices.htm#section4">Passing Arguments to StructureMap at Runtime</a> + <ul /> + </li> + <li> + <a href="RetrievingServices.htm#section5">"Try" to Get an Instance</a> + <ul /> + </li> + </ul> + </li> + <li> + <a href="AutoMocker.htm">Using the StructureMap AutoMocker</a> + <ul> + <li> + <a href="AutoMocker.htm#section0">How it Works</a> + <ul /> + </li> + <li> + <a href="AutoMocker.htm#section1">How it uses Mock Engines</a> + <ul /> + </li> + <li> + <a href="AutoMocker.htm#section2">Supplying Mocks or Stubs to the AutoMocker</a> + <ul /> + </li> + <li> + <a href="AutoMocker.htm#section3">Partial Mock the ClassU... [truncated message content] |
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. |
From: <jer...@us...> - 2009-01-11 21:16:22
|
Revision: 218 http://structuremap.svn.sourceforge.net/structuremap/?rev=218&view=rev Author: jeremydmiller Date: 2009-01-11 21:16:13 +0000 (Sun, 11 Jan 2009) Log Message: ----------- documentation update and BuildUp fix Modified Paths: -------------- trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/StructureMap/BuildSession.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs trunk/Source/StructureMap/Configuration/DSL/Registry.cs trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs trunk/Source/StructureMap/ConfigurationExpression.cs trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs trunk/Source/StructureMap/Graph/FindAllTypesFilter.cs trunk/Source/StructureMap/Interceptors/CompoundInterceptor.cs trunk/Source/StructureMap/Interceptors/EnrichmentInterceptor.cs trunk/Source/StructureMap/Interceptors/FilteredInstanceInterceptor.cs trunk/Source/StructureMap/Interceptors/InstanceInterceptor.cs trunk/Source/StructureMap/Interceptors/Interceptors.cs trunk/Source/StructureMap/Interceptors/MatchedTypeInterceptor.cs trunk/Source/StructureMap/Interceptors/NulloInterceptor.cs trunk/Source/StructureMap/Interceptors/StartupInterceptor.cs trunk/Source/StructureMap/Pipeline/ConfiguredInstance.Expressions.cs trunk/Source/StructureMap/Pipeline/Instance.cs trunk/Source/StructureMap/Pipeline/SmartInstance.cs trunk/Source/StructureMap/StructureMapConfiguration.cs trunk/Source/StructureMap/TypeExtensions.cs trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptAllInstancesOfPluginTypeTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptorTesting.cs trunk/Source/StructureMap.Testing/Graph/ConventionBasedSetterInjectionTester.cs trunk/Source/StructureMap.Testing/Graph/Interceptors/CompoundInterceptorTester.cs trunk/Source/StructureMap.Testing/Graph/Interceptors/MockTypeInterceptor.cs trunk/Source/StructureMap.Testing/Pipeline/InstanceTester.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj trunk/Source/StructureMap.Testing/TestData/AttributeNormalized.xml trunk/Source/StructureMap.Testing/TestData/ObjectMother.config Added Paths: ----------- trunk/Source/StructureMap.Testing/Examples/Interception.cs trunk/Source/StructureMap.Testing/TestData/ProfileSample.xml Modified: trunk/Source/HTML/ConstructorAndSetterInjection.htm =================================================================== --- trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-11 21:16:13 UTC (rev 218) @@ -265,7 +265,7 @@ --> <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> + [<span style="color: #2b91af;">Test</span>] <p style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">void</span> optional_setter_injection_with_string()</p> @@ -553,18 +553,60 @@ --> <!--EndFragment--> <hr /> - <h4>Applying Setter Injection to an Existing Object (BuildUp)</h4> + <h2>Applying Setter Injection to an Existing Object (BuildUp)</h2> <p>asdf</p> <hr /> - <h4><a name="SetterPolicies"></a>Creating Policies for Setter Injection</h4> + <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 - properties will be mandatory in the construction of objects. </p> + properties will be mandatory in the construction of objects. Setter + Injection policies are set with the new "SetAllProperties" method in the + Registry DSL:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red163\green21\blue21;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespace(\cf3 "StructureMap.Testing.Widget3"\cf0 );\par ??\par ?? policy.Matching(prop =>\par ?? \{\par ?? \cf4 return\cf0 prop.PropertyType.CanBeCastTo(\cf4 typeof\cf0 (\cf5 IService\cf0 ))\par ?? && !prop.Name.Contains(\cf3 "Ignore"\cf0 );\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.Matching(prop =></p> + <p style="margin: 0px;"> + + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">return</span> prop.PropertyType.CanBeCastTo(<span + style="color: blue;">typeof</span> (<span style="color: #2b91af;">IService</span>))</p> + <p style="margin: 0px;"> + + && !prop.Name.Contains(<span style="color: #a31515;">"Ignore"</span>);</p> + <p style="margin: 0px;"> + + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p>In the end, all you're doing is telling StructureMap that any public Setter that + matches a Predicate<PropertyInfo> policy should be a mandatory Setter. You + can make multiple declarations inside the + <a href="http://martinfowler.com/dslwip/NestedClosure.html">nested closure</a> + for SetAllProperties. <b>Any additional calls to SetAllProperties() are + purely additive.</b></p> + <p>In the sections below we'll look at some helper methods inside + SetAllProperties():</p> + <hr /> <h4>Specify a Setter Policy by Property Name</h4> <p>The sample below will make all public setter properties mandatory where the property name is suffixed by "Service." The call to NameMatches() takes in - a Predicate<string> that is a test against the property name.</p> + a Predicate<string> that is a test against the property name. The + NameMatches() method just applies a Predicate<string> test against the name of a + public setter.</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.NameMatches(name => name.EndsWith(\cf5 "Name"\cf0 ));\par ?? \});\par ?? \});} --> @@ -591,8 +633,36 @@ <!--EndFragment--> <hr /> <h4>Specify a Setter Policy by Property Type</h4> - <p> </p> + <p>Setter injection policies can also be defined by a simple test against the + PropertyInfo.PropertyType. Here's the shorthand 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 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.ForRequestedType<\cf4 IService\cf0 >().TheDefault.Is.Object(theService);\par ?? x.ForRequestedType<\cf4 IGateway\cf0 >().TheDefaultIsConcreteType<\cf4 DefaultGateway\cf0 >();\par ??\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.TypeMatches(type => type == \cf3 typeof\cf0 (\cf4 IService\cf0 ));\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.TypeMatches(type => type == <span style="color: blue;">typeof</span> (<span + style="color: #2b91af;">IService</span>));</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p>The "OfType<T>" method is shorthand for: policy.Matching( property => + typeof(T).IsAssignableTo(property.PropertyInfo) )</p> +<!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.OfType<\cf3 string\cf0 >();\par ?? policy.OfType<\cf4 IGateway\cf0 >();\par ?? \});\par ?? \});} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> @@ -619,7 +689,10 @@ });</p> </div> <!--EndFragment--> -<p> </p> +<p>You can also specify that all setter dependencies where the property type is + inside a namespace should be a mandatory setter (this check holds true for + subfolders of a namespace). This can be handy if you place all services in + a well known namespace.</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespaceContainingType<\cf4 ClassWithNamedProperties\cf0 >();\par ?? \});\par ?? \});} --> @@ -644,7 +717,7 @@ });</p> </div> <!--EndFragment--> -<p> </p> +<p>Here's another way to specify the namespace:</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespace(\cf5 "StructureMap.Testing.Widget3"\cf0 );\par ?? \});\par ?? \});} --> @@ -669,12 +742,9 @@ });</p> </div> <!--EndFragment--> -<p> </p> - <p> </p> +<hr /> - <hr /> - - <h4>Defining Setter Properties with Attributes</h4><p>Just use the [StructureMap.Attributes.SetterProperty] to denote properties that + <h2>Defining Setter Properties with Attributes</h2><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 @@ -737,7 +807,7 @@ </div> <!--EndFragment--> <hr /> - <h4>Defining Setter Properties in Xml</h4> + <h2>Defining Setter Properties in Xml</h2> <p>Setter properties can be defined in the Xml configuration by explicitly directing StructureMap to use setter properties while building a concrete type. In the Xml, Setter configuration is done with the exact syntax as constructor Modified: trunk/Source/StructureMap/BuildSession.cs =================================================================== --- trunk/Source/StructureMap/BuildSession.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/BuildSession.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -174,7 +174,7 @@ public virtual object ApplyInterception(Type pluginType, object actualValue) { if (actualValue == null) return null; - return _interceptorLibrary.FindInterceptor(actualValue.GetType()).Process(actualValue); + return _interceptorLibrary.FindInterceptor(actualValue.GetType()).Process(actualValue, this); } public virtual void RegisterDefault(Type pluginType, object defaultObject) Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -142,14 +142,56 @@ return target; }; - var interceptor = new PluginTypeInterceptor(typeof (PLUGINTYPE), function); + var interceptor = new PluginTypeInterceptor(typeof (PLUGINTYPE), (c, o) => + { + handler((PLUGINTYPE) o); + return o; + }); + graph.InterceptorLibrary.AddInterceptor(interceptor); }); return this; } + public CreatePluginFamilyExpression<PLUGINTYPE> InterceptWith(InstanceInterceptor interceptor) + { + _children.Add( + graph => + { + var typeInterceptor = new PluginTypeInterceptor(typeof(PLUGINTYPE), (c, o) => interceptor.Process(o, c)); + graph.InterceptorLibrary.AddInterceptor(typeInterceptor); + }); + + return this; + } + /// <summary> + /// Register an Action to run against any object of this PluginType immediately after + /// it is created, but before the new object is passed back to the caller + /// </summary> + /// <param name="handler"></param> + /// <returns></returns> + public CreatePluginFamilyExpression<PLUGINTYPE> OnCreation(Action<IContext, PLUGINTYPE> handler) + { + _children.Add( + graph => + { + Func<IContext, object, object> function = (c, o) => + { + handler(c, (PLUGINTYPE)o); + return o; + }; + + var interceptor = new PluginTypeInterceptor(typeof(PLUGINTYPE), function); + + graph.InterceptorLibrary.AddInterceptor(interceptor); + }); + + return this; + } + + /// <summary> /// Register a Func to run against any object of this PluginType immediately after it is created, /// but before the new object is passed back to the caller. Unlike <see cref="OnCreation">OnCreation()</see>, /// EnrichWith() gives the the ability to return a different object. Use this method for runtime AOP @@ -162,7 +204,7 @@ _children.Add( graph => { - Func<object, object> function = target => handler((PLUGINTYPE) target); + Func<IContext, object, object> function = (context, target) => handler((PLUGINTYPE) target); var interceptor = new PluginTypeInterceptor(typeof (PLUGINTYPE), function); graph.InterceptorLibrary.AddInterceptor(interceptor); @@ -172,6 +214,26 @@ } /// <summary> + /// Register a Func to run against any object of this PluginType immediately after it is created, + /// but before the new object is passed back to the caller. Unlike <see cref="OnCreation">OnCreation()</see>, + /// EnrichWith() gives the the ability to return a different object. Use this method for runtime AOP + /// scenarios or to return a decorator. + /// </summary> + /// <param name="handler"></param> + /// <returns></returns> + public CreatePluginFamilyExpression<PLUGINTYPE> EnrichWith(ContextEnrichmentHandler<PLUGINTYPE> handler) + { + _children.Add( + graph => + { + var interceptor = new PluginTypeInterceptor(typeof(PLUGINTYPE), (c, o) => handler(c, (PLUGINTYPE)o)); + graph.InterceptorLibrary.AddInterceptor(interceptor); + }); + + return this; + } + + /// <summary> /// Shortcut method to add an additional Instance to this Plugin Type /// as just a Concrete Type. This will only work if the Concrete Type /// has no primitive constructor or mandatory Setter arguments. @@ -209,6 +271,19 @@ } /// <summary> + /// Registers an IBuildInterceptor for this Plugin Type that executes before + /// any object of this PluginType is created. IBuildInterceptor's can be + /// used to create a custom scope + /// </summary> + /// <param name="interceptor"></param> + /// <returns></returns> + public CreatePluginFamilyExpression<PLUGINTYPE> BuildPolicyIs(IBuildInterceptor interceptor) + { + _alterations.Add(family => family.AddInterceptor(interceptor)); + return this; + } + + /// <summary> /// Largely deprecated and unnecessary with the ability to add Xml configuration files /// </summary> /// <param name="source"></param> Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/GenericFamilyExpression.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -113,6 +113,25 @@ { _registry.addExpression(graph => { + var interceptor = new PluginTypeInterceptor(_pluginType, (c, o) => func(o)); + graph.InterceptorLibrary.AddInterceptor(interceptor); + }); + + return this; + } + + /// <summary> + /// Register a Func to run against any object of this PluginType immediately after it is created, + /// but before the new object is passed back to the caller. Unlike <see cref="OnCreation">OnCreation()</see>, + /// EnrichWith() gives the the ability to return a different object. Use this method for runtime AOP + /// scenarios or to return a decorator. + /// </summary> + /// <param name="func"></param> + /// <returns></returns> + public GenericFamilyExpression EnrichWith(Func<IContext, object, object> func) + { + _registry.addExpression(graph => + { var interceptor = new PluginTypeInterceptor(_pluginType, func); graph.InterceptorLibrary.AddInterceptor(interceptor); }); Modified: trunk/Source/StructureMap/Configuration/DSL/Registry.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; using StructureMap.Configuration.DSL.Expressions; using StructureMap.Graph; using StructureMap.Interceptors; @@ -36,6 +37,14 @@ // Controlling Setter Injection Behavior CreatePluginFamilyExpression<PLUGINTYPE> FillAllPropertiesOfType<PLUGINTYPE>(); void SetAllProperties(Action<SetterConvention> action); + + /// <summary> + /// Use to programmatically select the constructor function of a concrete + /// class. Applies globally to all Containers in a single AppDomain. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="func"></param> + void SelectConstructor<T>(Expression<Func<T>> expression); } /// <summary> @@ -337,5 +346,16 @@ { action(new SetterConvention()); } + + /// <summary> + /// Use to programmatically select the constructor function of a concrete + /// class. Applies globally to all Containers in a single AppDomain. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="func"></param> + public void SelectConstructor<T>(Expression<Func<T>> expression) + { + PluginCache.GetPlugin(typeof(T)).UseConstructor(expression); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -19,6 +19,17 @@ { Matching(prop => prop.PropertyType == typeof (T)); } + + /// <summary> + /// Directs StructureMap to tread all public setters with + /// a PropertyType that matches the predicate as a + /// mandatory setter + /// </summary> + /// <param name="predicate"></param> + public void TypeMatches(Predicate<Type> predicate) + { + Matching(prop => predicate(prop.PropertyType)); + } /// <summary> /// Directs StructureMap to treat all public setters that match the Modified: trunk/Source/StructureMap/ConfigurationExpression.cs =================================================================== --- trunk/Source/StructureMap/ConfigurationExpression.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/ConfigurationExpression.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -86,16 +86,7 @@ return builder.Build(); } - /// <summary> - /// Use to programmatically select the constructor function of a concrete - /// class. Applies globally to all Containers in a single AppDomain. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="func"></param> - public void SelectConstructor<T>(Expression<Func<T>> expression) - { - PluginCache.GetPlugin(typeof (T)).UseConstructor(expression); - } + } Modified: trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs =================================================================== --- trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Diagnostics/WhatDoIHaveWriter.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -67,7 +67,7 @@ _writer.AddDivider('-'); var contents = new[] { - pluginType.PluginType.AssemblyQualifiedName ?? pluginType.PluginType.Name, + "{0} ({1})".ToFormat(pluginType.PluginType.GetName(), pluginType.PluginType.GetFullName()), string.Empty, string.Empty }; Modified: trunk/Source/StructureMap/Graph/FindAllTypesFilter.cs =================================================================== --- trunk/Source/StructureMap/Graph/FindAllTypesFilter.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Graph/FindAllTypesFilter.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -5,7 +5,7 @@ public class FindAllTypesFilter : TypeRules, ITypeScanner { private readonly Type _pluginType; - private Func<Type, string> _getName = type => type.FullName; + private Func<Type, string> _getName = type => PluginCache.GetPlugin(type).ConcreteKey; public FindAllTypesFilter(Type pluginType) { Modified: trunk/Source/StructureMap/Interceptors/CompoundInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/CompoundInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/CompoundInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -17,12 +17,12 @@ #region InstanceInterceptor Members - public object Process(object target) + public object Process(object target, IContext context) { object returnValue = target; foreach (InstanceInterceptor interceptor in _interceptors) { - returnValue = interceptor.Process(returnValue); + returnValue = interceptor.Process(returnValue, context); } return returnValue; Modified: trunk/Source/StructureMap/Interceptors/EnrichmentInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/EnrichmentInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/EnrichmentInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -1,20 +1,21 @@ namespace StructureMap.Interceptors { + // TODO -- gotta change to use IContext public class EnrichmentInterceptor<T> : InstanceInterceptor { - private readonly EnrichmentHandler<T> _handler; + private readonly ContextEnrichmentHandler<T> _handler; - public EnrichmentInterceptor(EnrichmentHandler<T> handler) + public EnrichmentInterceptor(ContextEnrichmentHandler<T> handler) { _handler = handler; } #region InstanceInterceptor Members - public object Process(object target) + public object Process(object target, IContext context) { - return _handler((T) target); + return _handler(context, (T) target); } #endregion Modified: trunk/Source/StructureMap/Interceptors/FilteredInstanceInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/FilteredInstanceInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/FilteredInstanceInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -22,10 +22,10 @@ /// </summary> public class PluginTypeInterceptor : TypeInterceptor { - private readonly Func<object, object> _function; + private readonly Func<IContext, object, object> _function; private readonly Type _pluginType; - public PluginTypeInterceptor(Type pluginType, Func<object, object> function) + public PluginTypeInterceptor(Type pluginType, Func<IContext, object, object> function) { _pluginType = pluginType; _function = function; @@ -38,9 +38,9 @@ return TypeRules.CanBeCast(_pluginType, type); } - public object Process(object target) + public object Process(object target, IContext context) { - return _function(target); + return _function(context, target); } #endregion Modified: trunk/Source/StructureMap/Interceptors/InstanceInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/InstanceInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/InstanceInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -8,6 +8,6 @@ /// </summary> public interface InstanceInterceptor { - object Process(object target); + object Process(object target, IContext context); } } \ No newline at end of file Modified: trunk/Source/StructureMap/Interceptors/Interceptors.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/Interceptors.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/Interceptors.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -1,4 +1,5 @@ namespace StructureMap.Interceptors { public delegate object EnrichmentHandler<T>(T target); + public delegate object ContextEnrichmentHandler<T>(IContext context, T target); } \ No newline at end of file Modified: trunk/Source/StructureMap/Interceptors/MatchedTypeInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/MatchedTypeInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/MatchedTypeInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -5,9 +5,9 @@ public class MatchedTypeInterceptor : TypeInterceptor { private readonly Predicate<Type> _match; - private Func<object, object> _interception; + private Func<IContext, object, object> _interception; - internal MatchedTypeInterceptor(Predicate<Type> match) + public MatchedTypeInterceptor(Predicate<Type> match) { _match = match; } @@ -19,16 +19,32 @@ return _match(type); } - public object Process(object target) + public object Process(object target, IContext context) { - return _interception(target); + return _interception(context, target); } #endregion + /// <summary> + /// Specify how objects matching the Type predicate + /// will be intercepted + /// </summary> + /// <param name="interception"></param> public void InterceptWith(Func<object, object> interception) { + _interception = (context, o) => interception(o); + } + + /// <summary> + /// Specify how objects matching the Type predicate + /// will be intercepted + /// </summary> + /// <param name="interception"></param> + public void InterceptWith(Func<IContext, object, object> interception) + { _interception = interception; } + } } \ No newline at end of file Modified: trunk/Source/StructureMap/Interceptors/NulloInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/NulloInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/NulloInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -4,7 +4,7 @@ { #region InstanceInterceptor Members - public object Process(object target) + public object Process(object target, IContext context) { return target; } Modified: trunk/Source/StructureMap/Interceptors/StartupInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Interceptors/StartupInterceptor.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Interceptors/StartupInterceptor.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -4,18 +4,18 @@ { public class StartupInterceptor<T> : InstanceInterceptor { - private readonly Action<T> _handler; + private readonly Action<IContext, T> _handler; - public StartupInterceptor(Action<T> handler) + public StartupInterceptor(Action<IContext, T> handler) { _handler = handler; } #region InstanceInterceptor Members - public object Process(object target) + public object Process(object target, IContext context) { - _handler((T) target); + _handler(context, (T) target); return target; } Modified: trunk/Source/StructureMap/Pipeline/ConfiguredInstance.Expressions.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/ConfiguredInstance.Expressions.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Pipeline/ConfiguredInstance.Expressions.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -21,6 +21,21 @@ /// <returns></returns> public ConfiguredInstance OnCreation<TYPE>(Action<TYPE> handler) { + var interceptor = new StartupInterceptor<TYPE>((c, o) => handler(o)); + Interceptor = interceptor; + + return this; + } + + /// <summary> + /// Register an Action to perform on the object created by this Instance + /// before it is returned to the caller + /// </summary> + /// <typeparam name="TYPE"></typeparam> + /// <param name="handler"></param> + /// <returns></returns> + public ConfiguredInstance OnCreation<TYPE>(Action<IContext, TYPE> handler) + { var interceptor = new StartupInterceptor<TYPE>(handler); Interceptor = interceptor; @@ -35,6 +50,20 @@ /// <returns></returns> public ConfiguredInstance EnrichWith<TYPE>(EnrichmentHandler<TYPE> handler) { + var interceptor = new EnrichmentInterceptor<TYPE>((c, o) => handler(o)); + Interceptor = interceptor; + + return this; + } + + /// <summary> + /// Register a Func to potentially enrich or substitute for the object + /// created by this Instance before it is returned to the caller + /// </summary> + /// <param name="handler"></param> + /// <returns></returns> + public ConfiguredInstance EnrichWith<TYPE>(ContextEnrichmentHandler<TYPE> handler) + { var interceptor = new EnrichmentInterceptor<TYPE>(handler); Interceptor = interceptor; Modified: trunk/Source/StructureMap/Pipeline/Instance.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/Instance.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Pipeline/Instance.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -106,7 +106,7 @@ // Allow the Interceptor a chance to enhance, configure, // wrap with a decorator, or even replace the rawValue - object finalValue = applyInterception(rawValue, pluginType); + object finalValue = applyInterception(rawValue, pluginType, session); markBuildStackFinish(session); @@ -172,12 +172,12 @@ } - private object applyInterception(object rawValue, Type pluginType) + private object applyInterception(object rawValue, Type pluginType, IContext context) { try { // Intercept with the Instance-specific InstanceInterceptor - return _interceptor.Process(rawValue); + return _interceptor.Process(rawValue, context); } catch (Exception e) { @@ -234,7 +234,7 @@ /// <returns></returns> public T OnCreation<TYPE>(Action<TYPE> handler) { - var interceptor = new StartupInterceptor<TYPE>(handler); + var interceptor = new StartupInterceptor<TYPE>((c, o) => handler(o)); Interceptor = interceptor; return thisInstance; @@ -249,6 +249,21 @@ /// <returns></returns> public T EnrichWith<TYPE>(EnrichmentHandler<TYPE> handler) { + var interceptor = new EnrichmentInterceptor<TYPE>((c, o) => handler(o)); + Interceptor = interceptor; + + return thisInstance; + } + + /// <summary> + /// Register a Func to potentially enrich or substitute for the object + /// created by this Instance before it is returned to the caller + /// </summary> + /// <typeparam name="TYPE"></typeparam> + /// <param name="handler"></param> + /// <returns></returns> + public T EnrichWith<TYPE>(ContextEnrichmentHandler<TYPE> handler) + { var interceptor = new EnrichmentInterceptor<TYPE>(handler); Interceptor = interceptor; Modified: trunk/Source/StructureMap/Pipeline/SmartInstance.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/SmartInstance.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/Pipeline/SmartInstance.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -39,6 +39,21 @@ /// <returns></returns> public SmartInstance<T> OnCreation(Action<T> handler) { + var interceptor = new StartupInterceptor<T>((c, o) => handler(o)); + Interceptor = interceptor; + + return this; + } + + /// <summary> + /// Register an Action to perform on the object created by this Instance + /// before it is returned to the caller + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="handler"></param> + /// <returns></returns> + public SmartInstance<T> OnCreation(Action<IContext, T> handler) + { var interceptor = new StartupInterceptor<T>(handler); Interceptor = interceptor; @@ -53,7 +68,7 @@ /// <returns></returns> public SmartInstance<T> EnrichWith(EnrichmentHandler<T> handler) { - var interceptor = new EnrichmentInterceptor<T>(handler); + var interceptor = new EnrichmentInterceptor<T>((c, o) => handler(o)); Interceptor = interceptor; return this; @@ -67,6 +82,34 @@ /// <returns></returns> public SmartInstance<T> EnrichWith<PLUGINTYPE>(EnrichmentHandler<PLUGINTYPE> handler) { + var interceptor = new EnrichmentInterceptor<PLUGINTYPE>((c, o) => handler(o)); + Interceptor = interceptor; + + return this; + } + + /// <summary> + /// Register a Func to potentially enrich or substitute for the object + /// created by this Instance before it is returned to the caller + /// </summary> + /// <param name="handler"></param> + /// <returns></returns> + public SmartInstance<T> EnrichWith(ContextEnrichmentHandler<T> handler) + { + var interceptor = new EnrichmentInterceptor<T>(handler); + Interceptor = interceptor; + + return this; + } + + /// <summary> + /// Register a Func to potentially enrich or substitute for the object + /// created by this Instance before it is returned to the caller + /// </summary> + /// <param name="handler"></param> + /// <returns></returns> + public SmartInstance<T> EnrichWith<PLUGINTYPE>(ContextEnrichmentHandler<PLUGINTYPE> handler) + { var interceptor = new EnrichmentInterceptor<PLUGINTYPE>(handler); Interceptor = interceptor; Modified: trunk/Source/StructureMap/StructureMapConfiguration.cs =================================================================== --- trunk/Source/StructureMap/StructureMapConfiguration.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/StructureMapConfiguration.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -103,8 +103,6 @@ /// </summary> public static void ResetAll() { - PluginCache.ResetAll(); - _sealed = false; _log = new GraphLog(); @@ -115,7 +113,6 @@ UseDefaultStructureMapConfigFile = false; IgnoreStructureMapConfig = false; - PluginCache.ResetAll(); ObjectFactory.Reset(); } Modified: trunk/Source/StructureMap/TypeExtensions.cs =================================================================== --- trunk/Source/StructureMap/TypeExtensions.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap/TypeExtensions.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -67,5 +67,29 @@ return null; } + public static string GetName(this Type type) + { + if (type.IsGenericType) + { + string[] parameters = Array.ConvertAll(type.GetGenericArguments(), t => t.GetName()); + var parameterList = string.Join(", ", parameters); + return "{0}<{1}>".ToFormat(type.Name, parameterList); + } + + return type.Name; + } + + public static string GetFullName(this Type type) + { + if (type.IsGenericType) + { + string[] parameters = Array.ConvertAll(type.GetGenericArguments(), t => t.GetName()); + var parameterList = string.Join(", ", parameters); + return "{0}<{1}>".ToFormat(type.Name, parameterList); + } + + return type.FullName; + } + } } \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptAllInstancesOfPluginTypeTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptAllInstancesOfPluginTypeTester.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptAllInstancesOfPluginTypeTester.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -1,6 +1,7 @@ using System; using NUnit.Framework; using StructureMap.Configuration.DSL; +using StructureMap.Interceptors; using StructureMap.Testing.Widget3; namespace StructureMap.Testing.Configuration.DSL @@ -79,12 +80,39 @@ } [Test] + public void custom_interceptor_for_all() + { + var interceptor = new MockInterceptor(); + IService service = getService("Green", r => + { + r.ForRequestedType<IService>().InterceptWith(interceptor) + .AddInstances(x => { x.ConstructedBy(() => new ColorService("Green")).WithName("Green"); }); + }); + + interceptor.Target.ShouldBeTheSameAs(service); + } + + public class MockInterceptor : InstanceInterceptor + { + public object Process(object target, IContext context) + { + Target = target; + return target; + } + + public object Target { get; set; } + } + + [Test] public void OnStartupForAll() { - Action<Registry> action = r => + Action<Registry> action = registry => { - r.ForRequestedType<IService>().OnCreation(s => _lastService = s) - .AddInstances(x => { x.ConstructedBy(() => new ColorService("Green")).WithName("Green"); }); + registry.ForRequestedType<IService>().OnCreation(s => _lastService = s) + .AddInstances(x => + { + x.ConstructedBy(() => new ColorService("Green")).WithName("Green"); + }); }; Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptorTesting.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptorTesting.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/InterceptorTesting.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -14,31 +14,50 @@ public void SetUp() { _lastService = null; + recorder = new ContextRecorder(); - _container = new Container(r => r.ForRequestedType<IService>().AddInstances(x => + _container = new Container(r => { - x.OfConcreteType<ColorService>() - .OnCreation(s => _lastService = s) - .WithName("Intercepted") - .WithCtorArg("color").EqualTo("Red"); + r.ForRequestedType<ContextRecorder>().TheDefault.IsThis(recorder); - x.OfConcreteType<ColorService>() - .WithName("NotIntercepted") - .WithCtorArg("color").EqualTo("Blue"); + r.ForRequestedType<IService>().AddInstances(x => + { + x.OfConcreteType<ColorService>() + .OnCreation(s => _lastService = s) + .WithName("Intercepted") + .WithCtorArg("color").EqualTo("Red"); - x.Object(new ColorService("Yellow")) - .WithName("Yellow") - .OnCreation<ColorService>(s => _lastService = s); + x.OfConcreteType<ColorService>() + .OnCreation((c, s) => c.GetInstance<ContextRecorder>().WasTouched = true) + .WithName("InterceptedWithContext") + .WithCtorArg("color").EqualTo("Red"); - x.ConstructedBy(() => new ColorService("Purple")).WithName("Purple") - .EnrichWith<IService>(s => new DecoratorService(s)); + x.OfConcreteType<ColorService>() + .WithName("NotIntercepted") + .WithCtorArg("color").EqualTo("Blue"); - x.OfConcreteType<ColorService>().WithName("Decorated").EnrichWith<IService>(s => new DecoratorService(s)) - .WithCtorArg("color").EqualTo("Orange"); + x.Object(new ColorService("Yellow")) + .WithName("Yellow") + .OnCreation<ColorService>(s => _lastService = s); - x.Object(new ColorService("Yellow")).WithName("Bad") - .OnCreation<ColorService>(obj => { throw new ApplicationException("Bad!"); }); - })); + x.ConstructedBy(() => new ColorService("Purple")).WithName("Purple") + .EnrichWith<IService>(s => new DecoratorService(s)); + + x.ConstructedBy(() => new ColorService("Purple")).WithName("DecoratedWithContext") + .EnrichWith<IService>((c, s) => + { + c.GetInstance<ContextRecorder>().WasTouched = true; + return new DecoratorService(s); + }); + + x.OfConcreteType<ColorService>().WithName("Decorated").EnrichWith<IService>( + s => new DecoratorService(s)) + .WithCtorArg("color").EqualTo("Orange"); + + x.Object(new ColorService("Yellow")).WithName("Bad") + .OnCreation<ColorService>(obj => { throw new ApplicationException("Bad!"); }); + }); + }); } #endregion @@ -46,8 +65,23 @@ private ColorService _lastService; private IContainer _container; + private ContextRecorder recorder; [Test] + public void call_the_build_context_with_startup() + { + _container.GetInstance<IService>("InterceptedWithContext"); + recorder.WasTouched.ShouldBeTrue(); + } + + [Test] + public void call_the_build_context_with_enrich() + { + _container.GetInstance<IService>("DecoratedWithContext"); + recorder.WasTouched.ShouldBeTrue(); + } + + [Test] public void DecorateAConstructedService() { var service = _container.GetInstance<IService>("Purple"); @@ -120,4 +154,9 @@ get { return _inner; } } } + + public class ContextRecorder + { + public bool WasTouched { get; set; } + } } \ No newline at end of file Added: trunk/Source/StructureMap.Testing/Examples/Interception.cs =================================================================== --- trunk/Source/StructureMap.Testing/Examples/Interception.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Examples/Interception.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using NUnit.Framework; +using StructureMap.Configuration.DSL; +using StructureMap.Interceptors; +using StructureMap; + +namespace StructureMap.Testing.Examples +{ + public interface IConnectionListener + { + void StartConnection(); + } + + public class ClassThatNeedsSomeBootstrapping : IConnectionListener + { + public void Start() + { + + } + + public void Connect(IConnectionPoint connection) + { + + } + + public void StartConnection() + { + throw new NotImplementedException(); + } + } + + public class LoggingDecorator : IConnectionListener + { + private readonly IConnectionListener _inner; + + public LoggingDecorator(IConnectionListener inner) + { + _inner = inner; + } + + public IConnectionListener Inner + { + get { return _inner; } + } + + public void StartConnection() + { + + } + } + + public class InterceptionRegistry : Registry + { + public InterceptionRegistry() + { + // Perform an Action<T> upon the object of type T + // just created before it is returned to the caller + ForRequestedType<ClassThatNeedsSomeBootstrapping>().TheDefault.Is + .OfConcreteType<ClassThatNeedsSomeBootstrapping>() + .OnCreation(x => x.Start()); + + // or... + + // You can also register an Action<IContext, T> to get access + // to all the services and capabilities of the BuildSession + ForRequestedType<ClassThatNeedsSomeBootstrapping>().TheDefault.Is + .OfConcreteType<ClassThatNeedsSomeBootstrapping>() + .OnCreation((context, x) => + { + var connection = context.GetInstance<IConnectionPoint>(); + x.Connect(connection); + }); + + + ForRequestedType<IConnectionListener>().TheDefault.Is + .OfConcreteType<ClassThatNeedsSomeBootstrapping>() + .EnrichWith(x => new LoggingDecorator(x)); + + ForRequestedType<IConnectionListener>().TheDefault.Is + .OfConcreteType<ClassThatNeedsSomeBootstrapping>() + .EnrichWith((context, x) => + { + var connection = context.GetInstance<IConnectionPoint>(); + x.Connect(connection); + + return new LoggingDecorator(x); + }); + + + ForRequestedType<IConnectionListener>().TheDefault.Is + .OfConcreteType<ClassThatNeedsSomeBootstrapping>() + .InterceptWith(new CustomInterceptor()); + + + + // Place the Interception at the PluginType level + ForRequestedType<IConnectionListener>() + .OnCreation(x => x.StartConnection()) // OnCreation + .EnrichWith(x => new LoggingDecorator(x)) // Enrich + .InterceptWith(new CustomInterceptor()) // Custom Interceptor + + + .TheDefaultIsConcreteType<ClassThatNeedsSomeBootstrapping>(); + + } + } + + [TestFixture, Explicit] + public class InterceptionRegistryInAction + { + [Test] + public void see_the_enrichment_with_a_decorator_in_action() + { + var container = new Container(new InterceptionRegistry()); + container.GetInstance<IConnectionListener>() + .ShouldBeOfType<LoggingDecorator>() + .Inner.ShouldBeOfType<ClassThatNeedsSomeBootstrapping>(); + } + } + + public class CustomInterceptor : InstanceInterceptor + { + public object Process(object target, IContext context) + { + // manipulate the target object and return a wrapped version + return wrapTarget(target); + } + + private object wrapTarget(object target) + { + throw new NotImplementedException(); + } + } + + + + + public interface IEventListener<T> + { + void ProcessEvent(T @event); + } + + public interface IEventAggregator + { + void RegisterListener<T>(IEventListener<T> listener); + void PublishEvent<T>(T @event); + } + + + + public class ListenerInterceptor : TypeInterceptor + { + public object Process(object target, IContext context) + { + // Assuming that "target" is an implementation of IEventListener<T>, + // we'll do a little bit of generics sleight of hand + // to register "target" with IEventAggregator + var eventType = target.GetType().FindInterfaceThatCloses(typeof (IEventListener<>)).GetGenericArguments()[0]; + var type = typeof (Registration<>).MakeGenericType(eventType); + Registration registration = (Registration) Activator.CreateInstance(type); + registration.RegisterListener(context, target); + + // we didn't change the target object, so just return it + return target; + } + + public bool MatchesType(Type type) + { + // ImplementsInterfaceTemplate is an Extension method in the + // StructureMap namespace that basically says: + // does this type implement any closed type of the open template type? + return type.ImplementsInterfaceTemplate(typeof (IEventListener<>)); + } + + // The inner type and interface is just a little trick to + // grease the generic wheels + public interface Registration + { + void RegisterListener(IContext context, object listener); + } + + public class Registration<T> : Registration + { + public void RegisterListener(IContext context, object listener) + { + var aggregator = context.GetInstance<IEventAggregator>(); + aggregator.RegisterListener<T>((IEventListener<T>) listener); + } + } + } + + public class ListeningRegistry : Registry + { + public ListeningRegistry() + { + RegisterInterceptor(new ListenerInterceptor()); + } + } +} Modified: trunk/Source/StructureMap.Testing/Graph/ConventionBasedSetterInjectionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/ConventionBasedSetterInjectionTester.cs 2009-01-08 13:28:57 UTC (rev 217) +++ trunk/Source/StructureMap.Testing/Graph/ConventionBasedSetterInjectionTester.cs 2009-01-11 21:16:13 UTC (rev 218) @@ -88,6 +88,27 @@ } [Test] + public void fill_all_properties_of_types_in_namespace_by_generic() + { + + var container = new Container(x => + { + x.SetAllProperties(policy => + { + policy.WithAnyTypeFromNamespaceContainingType<IService>(); + }); + }); + + var plugin = PluginCache.GetPlugin(typeof(ClassWithNamedProperties)); + + plugin.Setters.IsMandatory("Age").ShouldBeFalse(); + plugin.Setters.IsMandatory("FirstName").ShouldBeFalse(); + plugin.Setters.IsMandatory("LastName").ShouldBeFalse(); + plugin.Setters.IsMandatory("Gateway").ShouldBeTrue(); + plugin.Setters.IsMandatory("Service").ShouldBeTrue(); + } + + [Test] public void specify_setter_policy_and_construct_an_object() { var theService = new ColorService("red"); @@ -108,7 +129,30 @@ target.Gateway.ShouldBeOfType<DefaultGateway>(); } + [Test] + public void specify_setter_policy_by_a_predicate_on_property_type() + { + var theService = new ColorService("red"); + var container = new Container(x => + { + x.ForRequestedType<IService>().TheDefault.Is.Object(theService); + x.ForRequestedType<IGateway>().TheDefaultIsConcreteType<DefaultGateway>(); + + x.SetAllProperties(policy => + { + policy.TypeMatches(type => type == typeof (IService)); + }); + }); + + var target = container.GetInstance<ClassWithNamedProperties>(); + target.Service.ShouldBeTheSameAs(theService); + target.Gateway.ShouldBeNull(); + + + } + + public class ClassWithNamedProperties { public int Age { get; set; } Modified: trunk/Source/StructureMap.Testing/Graph/Interceptors/CompoundInterceptorTester.cs =================================================================== ---... [truncated message content] |
From: <jer...@us...> - 2009-01-08 13:29:03
|
Revision: 217 http://structuremap.svn.sourceforge.net/structuremap/?rev=217&view=rev Author: jeremydmiller Date: 2009-01-08 13:28:57 +0000 (Thu, 08 Jan 2009) Log Message: ----------- documentation update Modified Paths: -------------- trunk/Source/HTML/AttributeNormalized.htm trunk/Source/HTML/AutoMocker.htm trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/HTML/Diagnostics.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/HowDoesStructureMapWork.htm trunk/Source/HTML/Interception.htm trunk/Source/HTML/Menu.htm trunk/Source/HTML/NodeNormalized.htm trunk/Source/HTML/ScanningAssemblies.htm trunk/Source/HTML/XmlConfiguration.htm trunk/Source/HTML/XmlReference.htm Removed Paths: ------------- trunk/Source/HTML/ModularConfiguration.htm Modified: trunk/Source/HTML/AttributeNormalized.htm =================================================================== --- trunk/Source/HTML/AttributeNormalized.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/AttributeNormalized.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -5,6 +5,12 @@ <link rel="stylesheet" type="text/css" href="style.css" /> <script type="text/javascript" src="jquery-1.2.6.js"></script> <script type="text/javascript" src="structuremap.js"></script> + <style type="text/css"> + .style1 + { + font-weight: normal; + } + </style> </head> <body class="code"> <p>This style is a more terse configuration format that was @@ -12,7 +18,7 @@ Xml configuration by marking the <StructureMap> node with the MementoStyle="Attribute" attribute by default anytime you are using Xml configuration. </p> - <h2>Instance Root Node</h2> + <h2 class="style1">Instance Root Node</h2> <p>An Instance is defined in Xml starting from a root node. The actual name of the root node varies depending upon the context that an Instance is being configured. For example, the AddInstance, DefaultInstance, @@ -109,7 +115,7 @@ </div> <!--EndFragment--> <hr /> - <h2>Primitive Properties (Strings and basic value types)</h2> + <h2 class="style1">Primitive Properties (Strings and basic value types)</h2> <p>Primitive constructor or setter arguments are defined by adding an attribute @propertyName="propertyValue" to the instance node. A class with a string argument to the constructor,</p> @@ -131,7 +137,7 @@ </div> <hr /> - <h2>Long Strings</h2> + <h2 class="style1">Long Strings</h2> <p>There is an optional mode to define a property value inside a CDATA tag for very long strings like sql statements or Javascript templates. </p> @@ -149,7 +155,7 @@ </div> <hr /> - <h2>Enumeration Properties</h2> + <h2 class="style1">Enumeration Properties</h2> <p>Enumeration arguments are defined the same way as primitive properties. Use the string names of the enumeration for the values.</p> @@ -181,7 +187,7 @@ <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: #800000">Instance</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Cow"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Maggie" </span><span style="color: #FF0000">Breed</span><span style="color: blue;">="Angus" /></span></pre> </div> <hr /> - <h2>Child Properties</h2> + <h2 class="style1">Dependency Properties</h2> <p>Child properties of non-primitive types are defined as embedded memento nodes. Child properties can be either defined inline or use a reference to a named instance of the @@ -230,7 +236,7 @@ <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">StructureMap.Testing.Widget.Child</span><span style="color: blue;">></span> </pre> </div> <hr /> - <h2>Non Primitive Array Property</h2> + <h2 class="style1">Non Primitive Array Property</h2> <p>If a property or constructor argument is an array of a non-primitive type, create a child node to the top level instance node with the name of the property. Simply add new InstanceMemento nodes with the name <Child> under the property @@ -262,7 +268,7 @@ <p style="margin: 0px;"> </p> <hr /> </div> -<h2>Primitive Arrays</h2> +<h2 class="style1">Primitive Arrays</h2> <p>Primitive arrays like string[] or int[] can be defined in Xml. For a class with arguments like:</p> <!-- @@ -358,7 +364,7 @@ </div> <!--EndFragment--> <hr /> - <h2>Dictionaries and NameValueCollection</h2> + <h2 class="style1">Dictionaries and NameValueCollection</h2> <p>Any form of IDictionary<Key, Value> or a NameValueCollection can be configured in Xml by the following syntax. Say you have a class that needs a Dictionary of properties:</p> Modified: trunk/Source/HTML/AutoMocker.htm =================================================================== --- trunk/Source/HTML/AutoMocker.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/AutoMocker.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -1,9 +1,12 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>Auto Mocking Container with StructureMap</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> - + Forthcoming... ETA: 1st Qtr 2009 </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/ConstructorAndSetterInjection.htm =================================================================== --- trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/ConstructorAndSetterInjection.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -5,6 +5,12 @@ <link rel="stylesheet" type="text/css" href="style.css" /> <script type="text/javascript" src="jquery-1.2.6.js"></script> <script type="text/javascript" src="structuremap.js"></script> + <style type="text/css"> + .style1 + { + font-weight: normal; + } + </style> </head> <body> @@ -132,13 +138,82 @@ </div> <!--EndFragment--> <h4>Overriding the Constructor in the Registry DSL</h4> - <p>TODO</p> + <p>StructureMap has always allowed you to override the constructor choice with an + attribute, but increasingly, many people are unwilling to use attributes in + their code for infrastructure concerns. Other times you may want to + override the constructor choice of a class that you don't control. Either + way, it would be useful to select the constructor function used by StructureMap + to build a concrete code in the Registry DSL. The syntax to do just that + is shown below:</p> + <p>Let's say that you have this class (from the unit tests):</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassWithTwoConstructors\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 int\cf0 _age;\par ?? \cf3 private\cf0 \cf3 string\cf0 _name;\par ??\par ?? \cf3 public\cf0 ClassWithTwoConstructors(\cf3 int\cf0 age, \cf3 string\cf0 name)\par ?? \{\par ?? \cf4 Assert\cf0 .Fail(\cf5 "Should not be called"\cf0 );\par ??\par ?? _age = age;\par ?? _name = name;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf3 bool\cf0 WasConstructedWithNarrowCtor = \cf3 false\cf0 ;\par ?? \cf3 public\cf0 ClassWithTwoConstructors(\cf3 int\cf0 age)\par ?? \{\par ?? _age = age;\par ?? WasConstructedWithNarrowCtor = \cf3 true\cf0 ;\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">ClassWithTwoConstructors</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ClassWithTwoConstructors(<span style="color: blue;">int</span> age, + <span style="color: blue;">string</span> name)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ClassWithTwoConstructors(<span style="color: blue;">int</span> age)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>By default, StructureMap would choose the "greediest" constructor. In this + case, it would be the constructor that takes in "age" and "name." To force + StructureMap into using the other constructor, use the SelectConstructor() + method on the Registry:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SelectConstructor<\cf4 ClassWithTwoConstructors\cf0 >(()=>\cf3 new\cf0 \cf4 ClassWithTwoConstructors\cf0 (0));\par ?? x.ForConcreteType<\cf4 ClassWithTwoConstructors\cf0 >().Configure\par ?? .WithCtorArg(\cf5 "age"\cf0 ).EqualTo(34);\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SelectConstructor<<span style="color: #2b91af;">ClassWithTwoConstructors</span>>(()=><span + style="color: blue;">new</span> <span style="color: #2b91af;"> + ClassWithTwoConstructors</span>(0));</p> + <p style="margin: 0px;"> + + x.ForConcreteType<<span style="color: #2b91af;">ClassWithTwoConstructors</span>>().Configure</p> + <p style="margin: 0px;"> + + .WithCtorArg(<span style="color: #a31515;">"age"</span>).EqualTo(34);</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p>The argument to the SelectConstructor is an Expression of type + Expression<Func<T>> where T is the concrete class. StructureMap parses the + Expression to find the constructor function in the Expression object.</p> <hr /> - <h2>Using Setter Injection</h2> + <h2 class="style1">Using Setter Injection</h2> <p>Setter injection is a pattern of "injecting" dependencies via public properties. Setter Injection with StructureMap is somewhat a second class citizen, but this is partially by design. My strong recommendation is to use @@ -478,11 +553,124 @@ --> <!--EndFragment--> <hr /> - <h4><a name="SetterPolicies"></a>Creating Policies for Setter Injection</h4><p>TODO</p> - <hr /> <h4>Applying Setter Injection to an Existing Object (BuildUp)</h4> - <p>TODO</p> + <p>asdf</p> + <hr /> + <h4><a name="SetterPolicies"></a>Creating Policies for Setter Injection</h4> + <p>New in StructureMap 2.5.2+ is the ability to create setter injection policies. + What this means is that you create conventions to define which public setter + properties will be mandatory in the construction of objects. </p> + <h4>Specify a Setter Policy by Property Name</h4> + <p>The sample below will make all public setter properties mandatory where the + property name is suffixed by "Service." The call to NameMatches() takes in + a Predicate<string> that is a test against the property name.</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.NameMatches(name => name.EndsWith(\cf5 "Name"\cf0 ));\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.NameMatches(name => name.EndsWith(<span style="color: #a31515;">"Service"</span>));</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<hr /> + <h4>Specify a Setter Policy by Property Type</h4> + <p> </p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.OfType<\cf3 string\cf0 >();\par ?? policy.OfType<\cf4 IGateway\cf0 >();\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.OfType<<span style="color: blue;">string</span>>();</p> + <p style="margin: 0px;"> + + policy.OfType<<span style="color: #2b91af;">IGateway</span>>();</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p> </p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespaceContainingType<\cf4 ClassWithNamedProperties\cf0 >();\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.WithAnyTypeFromNamespaceContainingType<<span style="color: #2b91af;">ClassWithNamedProperties</span>>();</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p> </p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 var\cf0 container = \cf3 new\cf0 \cf4 Container\cf0 (x =>\par ?? \{\par ?? x.SetAllProperties(policy =>\par ?? \{\par ?? policy.WithAnyTypeFromNamespace(\cf5 "StructureMap.Testing.Widget3"\cf0 );\par ?? \});\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + x.SetAllProperties(policy =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + policy.WithAnyTypeFromNamespace(<span style="color: #a31515;">"StructureMap.Testing.Widget3"</span>);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p> </p> + <p> </p> <hr /> Modified: trunk/Source/HTML/Diagnostics.htm =================================================================== --- trunk/Source/HTML/Diagnostics.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/Diagnostics.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -2,8 +2,13 @@ <html> <head> <title>Diagnostics</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> + <p>More information coming, ETA: 1st Qtr 2009</p> + <h2>What do I Have?</h2> <p>text</p> <hr /> Modified: trunk/Source/HTML/HTML.csproj =================================================================== --- trunk/Source/HTML/HTML.csproj 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/HTML.csproj 2009-01-08 13:28:57 UTC (rev 217) @@ -64,7 +64,6 @@ <Content Include="FeatureList.htm" /> <Content Include="HowDoesStructureMapWork.htm" /> <Content Include="InversionOfControl.htm" /> - <Content Include="ModularConfiguration.htm" /> <Content Include="Profiles.htm" /> <Content Include="Scoping.htm" /> <Content Include="UsingAttributes.htm" /> Modified: trunk/Source/HTML/HowDoesStructureMapWork.htm =================================================================== --- trunk/Source/HTML/HowDoesStructureMapWork.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/HowDoesStructureMapWork.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -1,9 +1,12 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>How does StructureMap Work?</title> + <link rel="stylesheet" type="text/css" href="style.css" /> + <script type="text/javascript" src="jquery-1.2.6.js"></script> + <script type="text/javascript" src="structuremap.js"></script> </head> <body> - + More information coming 1st Qtr 2009 </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/Interception.htm =================================================================== --- trunk/Source/HTML/Interception.htm 2009-01-05 04:27:51 UTC (rev 216) +++ trunk/Source/HTML/Interception.htm 2009-01-08 13:28:57 UTC (rev 217) @@ -7,19 +7,639 @@ <script type="text/javascript" src="structuremap.js"></script> </head> <body> - <p>Introduction</p> + <p>StructureMap 2.5+ added the ability to postprocess or even intercept and replace + the objects being created. While StructureMap will never include its own + Aspect Oriented Programming model (the world does not need a new one), the + interception techniques shown below could be used to apply runtime AOP from + existing AOP tools like the Policy Injection Application Block from Microsoft.</p> + <p>In general, interception is specified in three ways:</p> + <ol> + <li>OnCreation() -- Registers an Action to run against the new object after creation</li> + <li>EnrichWith() -- Registers a Func that runs against the new object after creation + and gives you the option of returning a different object than the original + object</li> + <li>A custom class that implements the TypeInterceptor interface (the runtime model + behind all the interception techniques)</li> + </ol> - <h2>Title</h2> - <p>Content</p> + + <p> + </p> + + + <h2>Intercept a Single Instance</h2> + <p>You can specify interception for a single Instance. This interception could + be combined with other Interception policies, but users should be cautious about + this. </p> + <h4>Run an Action Against an Object</h4> + <p>Some classes may require some extra bootstrapping work before they are ready to + be used. While I recommend building classes in such a way that the new + objects are ready to function after calling the constructor function, not every + class you will encounter will follow this rule. For that reason, + StructureMap has the ability to register an Action<T> to run against a newly + created object before it is returned to the requesting code. You can + register that Action on an individual Instance:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 InterceptionRegistry\cf0 : \cf4 Registry\par ??\cf0 \{\par ?? \cf3 public\cf0 InterceptionRegistry()\par ?? \{\par ?? \cf5 // Perform an Action<T> upon the object of type T \par ??\cf0 \cf5 // just created before it is returned to the caller\par ??\cf0 ForRequestedType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation(x => x.Start());\par ?? \par ?? \cf5 // or...\par ??\par ??\cf0 \cf5 // You can also register an Action<IContext, T> to get access\par ??\cf0 \cf5 // to all the services and capabilities of the BuildSession\par ??\cf0 ForRequestedType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation((context, x) =>\par ?? \{\par ?? \cf3 var\cf0 connection = context.GetInstance<\cf4 IConnectionPoint\cf0 >();\par ?? x.Connect(connection);\par ?? \});\par ??\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">InterceptionRegistry</span> : + <span style="color: #2b91af;">Registry</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + InterceptionRegistry()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;"> + // Perform an Action<T> upon the object of type T </span> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // just created before it is returned to the caller</span></p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .OnCreation(x => x.Start());</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // or...</span></p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;"> + // You can also register an Action<IContext, T> to get access</span></p> + <p style="margin: 0px;"> + <span style="color: green;"> + // to all the services and capabilities of the BuildSession</span></p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .OnCreation((context, x) =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> connection = context.GetInstance<<span + style="color: #2b91af;">IConnectionPoint</span>>();</p> + <p style="margin: 0px;"> + + x.Connect(connection);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> + <h4>Wrap or Substitute the Returned Object</h4> + <p>Sometimes you may want to wrap the constructed object in some sort of Decorator + or apply runtime AOP to the new object. In this case, StructureMap will + allow you to substitute the constructed object for the new wrapped object -- + with the restriction that the object returned must be assignable to the + requested PluginType. Let's consider the case of using a + <a href="http://resharper.codebetter.com/blogs/jeremy.miller/archive/2005/09/02/131613.aspx"> + Decorator</a> pattern to add logging to an existing service:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 LoggingDecorator\cf0 : \cf4 IConnectionListener\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 IConnectionListener\cf0 _inner;\par ??\par ?? \cf3 public\cf0 LoggingDecorator(\cf4 IConnectionListener\cf0 inner)\par ?? \{\par ?? _inner = inner;\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">LoggingDecorator</span> : + <span style="color: #2b91af;">IConnectionListener</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">readonly</span> <span style="color: #2b91af;"> + IConnectionListener</span> _inner;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + LoggingDecorator(<span style="color: #2b91af;">IConnectionListener</span> inner)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _inner = inner;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>When you register an instance of IConnectionListener, you can specify that the + constructed object get wrapped with a decorator using the EnrichWith() syntax + like this:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red0\green128\blue0;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 InterceptionRegistry()\par ?? \{\par ?? \cf4 // Perform an Action<T> upon the object of type T \par ??\cf0 \cf4 // just created before it is returned to the caller\par ??\cf0 ForRequestedType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation(x => x.Start());\par ?? \par ?? \cf4 // or...\par ??\par ??\cf0 \cf4 // You can also register an Action<IContext, T> to get access\par ??\cf0 \cf4 // to all the services and capabilities of the BuildSession\par ??\cf0 ForRequestedType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .OnCreation((context, x) =>\par ?? \{\par ?? \cf3 var\cf0 connection = context.GetInstance<\cf5 IConnectionPoint\cf0 >();\par ?? x.Connect(connection);\par ?? \});\par ??\par ??\par ?? ForRequestedType<\cf5 IConnectionListener\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf5 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .EnrichWith(x => \cf3 new\cf0 \cf5 LoggingDecorator\cf0 (x));\par ??\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + InterceptionRegistry()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .EnrichWith(x => <span style="color: blue;">new</span> + <span style="color: #2b91af;">LoggingDecorator</span>(x));</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>In the sample registration above, a call to + Container.GetInstance<IConnectionListener>() will result in a new + ClassThatNeedsSomeBootstrapping wrapped in a LoggingDecorator object:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 [\cf3 Test\cf0 ]\par ?? \cf4 public\cf0 \cf4 void\cf0 see_the_enrichment_with_a_decorator_in_action()\par ?? \{\par ?? \cf4 var\cf0 container = \cf4 new\cf0 \cf3 Container\cf0 (\cf4 new\cf0 \cf3 InterceptionRegistry\cf0 ());\par ?? container.GetInstance<\cf3 IConnectionListener\cf0 >()\par ?? .ShouldBeOfType<\cf3 LoggingDecorator\cf0 >()\par ?? .Inner.ShouldBeOfType<\cf3 ClassThatNeedsSomeBootstrapping\cf0 >();\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + [<span style="color: #2b91af;">Test</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">void</span> + see_the_enrichment_with_a_decorator_in_action()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + var</span> container = <span style="color: blue;">new</span> + <span style="color: #2b91af;">Container</span>(<span style="color: blue;">new</span> + <span style="color: #2b91af;">InterceptionRegistry</span>());</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">IConnectionListener</span>>()</p> + <p style="margin: 0px;"> + + .ShouldBeOfType<<span style="color: #2b91af;">LoggingDecorator</span>>()</p> + <p style="margin: 0px;"> + + .Inner.ShouldBeOfType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>();</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>There is also an overload of EnrichWith() that takes in the IContext object:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 ForRequestedType<\cf3 IConnectionListener\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf3 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .EnrichWith((context, x) =>\par ?? \{\par ?? \cf4 var\cf0 connection = context.GetInstance<\cf3 IConnectionPoint\cf0 >();\par ?? x.Connect(connection);\par ??\par ?? \cf4 return\cf0 \cf4 new\cf0 \cf3 LoggingDecorator\cf0 (x);\par ?? \});} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .EnrichWith((context, x) =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: blue;">var</span> connection = context.GetInstance<<span + style="color: #2b91af;">IConnectionPoint</span>>();</p> + <p style="margin: 0px;"> + + x.Connect(connection);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: blue;">return</span> <span style="color: blue;">new</span> + <span style="color: #2b91af;">LoggingDecorator</span>(x);</p> + <p style="margin: 0px;"> + });</p> + </div> +<!--EndFragment--> +<p>See <a href="UsingSessionContext.htm">Using the Session Context</a> for more + information on using the IContext.</p> + <hr /> + <h4>With a Custom Interceptor</h4> + <p>To write a custom Interceptor for a single Instance, create a new class that + implements the InstaneInterceptor interface:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 interface\cf0 \cf4 InstanceInterceptor\par ??\cf0 \{\par ?? \cf3 object\cf0 Process(\cf3 object\cf0 target, \cf4 IContext\cf0 context);\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">interface</span> + <span style="color: #2b91af;">InstanceInterceptor</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">object</span> Process(<span + style="color: blue;">object</span> target, <span style="color: #2b91af;"> + IContext</span> context);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p> with a class like this:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;\red0\green128\blue0;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 CustomInterceptor\cf0 : \cf4 InstanceInterceptor\par ??\cf0 \{\par ?? \cf3 public\cf0 \cf3 object\cf0 Process(\cf3 object\cf0 target, \cf4 IContext\cf0 context)\par ?? \{\par ?? \cf5 // manipulate the target object and return a wrapped version\par ??\cf0 \cf3 return\cf0 wrapTarget(target);\par ?? \}\par ??\par ?? \cf3 private\cf0 \cf3 object\cf0 wrapTarget(\cf3 object\cf0 target)\par ?? \{\par ?? \cf3 throw\cf0 \cf3 new\cf0 \cf4 NotImplementedException\cf0 ();\par ?? \}\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">CustomInterceptor</span> : + <span style="color: #2b91af;">InstanceInterceptor</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + <span style="color: blue;">object</span> Process(<span style="color: blue;">object</span> + target, <span style="color: #2b91af;">IContext</span> context)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;"> + // manipulate the target object and return a wrapped version</span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> + return</span> wrapTarget(target);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">object</span> wrapTarget(<span style="color: blue;">object</span> + target)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + throw</span> <span style="color: blue;">new</span> <span style="color: #2b91af;"> + NotImplementedException</span>();</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Then, register the a new object instance of the CustomerInterceptor:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 ForRequestedType<\cf3 IConnectionListener\cf0 >().TheDefault.Is\par ?? .OfConcreteType<\cf3 ClassThatNeedsSomeBootstrapping\cf0 >()\par ?? .InterceptWith(\cf4 new\cf0 \cf3 CustomInterceptor\cf0 ());} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>().TheDefault.Is</p> + <p style="margin: 0px;"> + + .OfConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>()</p> + <p style="margin: 0px;"> + + .InterceptWith(<span style="color: blue;">new</span> + <span style="color: #2b91af;">CustomInterceptor</span>());</p> + </div> <hr /> + + + + <h2>Apply Interception to all Instances of a PluginType</h2> + <p>The same OnCreation(), EnrichWith(), and InterceptWith() methods can be applied + to all Instances of a given PluginType off of the ForRequestedType() or + BuildInstancesOf() methods of the <a href="RegistryDSL.htm">Registry DSL</a>:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green128\blue0;\red43\green145\blue175;\red0\green0\blue255;}??\fs20 \cf3 // Place the Interception at the PluginType level\par ??\cf0 ForRequestedType<\cf4 IConnectionListener\cf0 >()\par ?? .OnCreation(x => x.StartConnection()) \cf3 // OnCreation\par ??\cf0 .EnrichWith(x => \cf5 new\cf0 \cf4 LoggingDecorator\cf0 (x)) \cf3 // Enrich\par ??\cf0 .InterceptWith(\cf5 new\cf0 \cf4 CustomInterceptor\cf0 ()) \cf3 // Custom Interceptor\par ??\par ??\par ??\cf0 .TheDefaultIsConcreteType<\cf4 ClassThatNeedsSomeBootstrapping\cf0 >();} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Place the Interception at the PluginType level</span></p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: #2b91af;">IConnectionListener</span>>()</p> + <p style="margin: 0px;"> + + .OnCreation(x => x.StartConnection()) + <span style="color: green;">// OnCreation</span></p> + <p style="margin: 0px;"> + + .EnrichWith(x => <span style="color: blue;">new</span> + <span style="color: #2b91af;">LoggingDecorator</span>(x)) + <span style="color: green;">// Enrich</span></p> + <p style="margin: 0px;"> + + .InterceptWith(<span style="color: blue;">new</span> + <span style="color: #2b91af;">CustomInterceptor</span>()) + <span style="color: green;">// Custom Interceptor</span></p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + .TheDefaultIsConcreteType<<span style="color: #2b91af;">ClassThatNeedsSomeBootstrapping</span>>();</p> + </div> +<!--EndFragment--> +<p>Note that these methods can be used in combination with each other and even + multiple times for the same type. All additional calls are additive. + Use with caution!</p> + <hr /> - <h2>Title</h2> - <p>Content</p> + + <h2>Apply Interception to all Types Matching a Criteria</h2> + <p>If an interception policy is simple, you can just register the interception + policy with the IfTypeMatches( Predicate<Type> ).InterceptWith( + Lambda ) syntax:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 registry.IfTypeMatches(type => type.Equals(\cf3 typeof\cf0 (\cf4 BlueSomething\cf0 )))\par ?? .InterceptWith(rawInstance => \cf3 new\cf0 \cf4 WrappedSomething\cf0 ((\cf4 IAnInterfaceOfSomeSort\cf0 ) rawInstance));} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + registry.IfTypeMatches(type + => type.Equals(<span style="color: blue;">typeof</span> (<span + style="color: #2b91af;">BlueSomething</span>)))</p> + <p style="margin: 0px;"> + + .InterceptWith(rawInstance => <span style="color: blue;">new</span> + <span style="color: #2b91af;">WrappedSomething</span>((<span + style="color: #2b91af;">IAnInterfaceOfSomeSort</span>) rawInstance));</p> + </div> +<!--EndFragment--> +<p>Please note that when StructureMap encounters a new concrete type for the first + time, it searches for all TypeInterceptors that match that the concrete type, + and caches these TypeInterceptors against the concrete type for future usage. + The long and short of this is that any filter on the type is only going to be + evaluated once.</p> <hr /> - <h2>Title</h2> - <p>Content</p> + <h2>Creating a Custom Type Interceptor</h2> + <p>Sooner or later the Fluent Interface registration of TypeInterceptors will not be + adequate. In that case, you can create a custom class that implements the + TypeInterceptor interface:</p> +<!-- +{\rtf1\ansi\ansicpg\lang1024\noproof1252\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red128\green128\blue128;\red0\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 ///\cf4 \cf3 <summary>\par ??\cf0 \cf3 ///\cf4 A TypeInterceptor that is only applied if the MatchesType()\par ??\cf0 \cf3 ///\cf4 method is true for a given Type\par ??\cf0 \cf3 ///\cf4 \cf3 </summary>\par ??\cf0 \cf5 public\cf0 \cf5 interface\cf0 \cf6 TypeInterceptor\cf0 : \cf6 InstanceInterceptor\par ??\cf0 \{\par ?? \cf3 ///\cf4 \cf3 <summary>\par ??\cf0 \cf3 ///\cf4 Does this TypeInterceptor apply to the given type?\par ??\cf0 \cf3 ///\cf4 \cf3 </summary>\par ??\cf0 \cf3 ///\cf4 \cf3 <param name="type"></param>\par ??\cf0 \cf3 ///\cf4 \cf3 <returns></returns>\par ??\cf0 \cf5 bool\cf0 MatchesType(\cf6 Type\cf0 type);\par ?? \}} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> </span> + <span style="color: gray;"><summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> A + TypeInterceptor that is only applied if the MatchesType()</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> method is + true for a given Type</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span style="color: green;"> </span> + <span style="color: gray;"></summary></span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">interface</span> + <span style="color: #2b91af;">TypeInterceptor</span> : + <span style="color: #2b91af;">InstanceInterceptor</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> Does this TypeInterceptor apply to the given type?</span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"></summary></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><param + name="type"></param></span></p> + <p style="margin: 0px;"> + <span style="color: gray;">///</span><span + style="color: green;"> </span><span style="color: gray;"><returns></returns></span></p> + <p style="margin: 0px;"> + <span style="color: blue;">bool</span> MatchesType(<span + style="color: #2b91af;">Type</span> type);</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p>Registered TypeInterceptor objects are applied against any object created by + StructureMap if the type of the new object meets the MatchesType() method of + TypeInterceptor. You can happil... [truncated message content] |
From: <jer...@us...> - 2009-01-05 04:28:02
|
Revision: 216 http://structuremap.svn.sourceforge.net/structuremap/?rev=216&view=rev Author: jeremydmiller Date: 2009-01-05 04:27:51 +0000 (Mon, 05 Jan 2009) Log Message: ----------- more documentation Modified Paths: -------------- trunk/Source/HTML/AutoWiring.htm trunk/Source/HTML/ChangingConfigurationAtRuntime.htm trunk/Source/HTML/Concepts.htm trunk/Source/HTML/ConfiguringStructureMap.htm trunk/Source/HTML/Default.htm trunk/Source/HTML/Generics.htm trunk/Source/HTML/Glossary.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/InstanceExpression.htm trunk/Source/HTML/Menu.htm trunk/Source/HTML/NodeNormalized.htm trunk/Source/HTML/RegistryDSL.htm trunk/Source/HTML/RetrievingServices.htm trunk/Source/HTML/ScanningAssemblies.htm trunk/Source/HTML/UsingSessionContext.htm trunk/Source/HTML/style.css Added Paths: ----------- trunk/Source/HTML/DependencyInjection.htm trunk/Source/HTML/InversionOfControl.htm Modified: trunk/Source/HTML/AutoWiring.htm =================================================================== --- trunk/Source/HTML/AutoWiring.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/AutoWiring.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -82,7 +82,9 @@ <h2> Example</h2> <p> - Typically, you’ll try to minimize the number of service locator[LINK] usages in + Typically, you’ll try to minimize the number of + <a href="%20%20%20%20%20%20%20%20%20%20%20%20Typically,%20you’ll%20try%20to%20minimize%20the%20number%20of%20Service%20Locator%20usages%20in%20">Service Locator</a> + (Container.Get*****) 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 Modified: trunk/Source/HTML/ChangingConfigurationAtRuntime.htm =================================================================== --- trunk/Source/HTML/ChangingConfigurationAtRuntime.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/ChangingConfigurationAtRuntime.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -259,8 +259,8 @@ functionality in favor of the simple ObjectFactory/Container.Inject<T>(T object) methods.</p> <p>My strong advice is to not use the Container or ObjectFactory in unit tests in - the mass majority of cases. Rather, my advice is to use simple Dependency - Injection[LINK] to inject mock objects during unit tests. However, there + the mass majority of cases. Rather, my advice is to use simple + <a href="DependencyInjection.htm">Dependency Injection</a> to inject mock objects during unit tests. However, there are still times when you want or need a class to use the Container or ObjectFactory itself to get dependencies at runtime. For that case, here is a sample:</p> Modified: trunk/Source/HTML/Concepts.htm =================================================================== --- trunk/Source/HTML/Concepts.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/Concepts.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -1,9 +1,438 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title></title> + <title>Software Design Concepts</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> + Before you jump into using StructueMap in anger, there are some design concepts + that can help you get the most out of an IoC tool. This web page is + strictly about conceptual design fundamentals, and not particularly specific to + StructureMap itself. I think this stuff is important to real world + development. You might not memorize the "Liskov Substitution Principle" + text, but you're code will be better for following its intent -- even if you + don't particulary know the exact term for LSP. When you read this section, + please focus on the concepts and any class's role within a system rather than + get caught up in coding details like "why is he using an AddressController + instead of that being part of another class?"</p> + <p> + </p> + <h2> + Design Concepts</h2> + <p> + Over the years a series of concepts and principles have been discovered and + developed to describe well-structured Object Oriented systems. To most + effectively use StructureMap, or any other IoC tool for that matter, your system + needs to be designed with these principles first: + </p> + <ul> + <li><a href="http://en.wikipedia.org/wiki/Separation_of_concerns" + mce_href="http://en.wikipedia.org/wiki/Separation_of_concerns">Separation of + Concerns</li> + <li><a href="http://msdn.microsoft.com/en-us/magazine/cc546578.aspx" + mce_href="http://msdn.microsoft.com/en-us/magazine/cc546578.aspx">Open + Closed Principle, the Single Responsibility Principle, and the Liskov + Substitution Principle</a></li> + <li><a href="http://codebetter.com/blogs/jeremy.miller/pages/129542.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/pages/129542.aspx"> + Responsibilities, Cohesion, and Coupling</a></li> + <li><a href="http://codebetter.com/blogs/jeremy.miller/archive/2007/01/08/Orthogonal-Code.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/archive/2007/01/08/Orthogonal-Code.aspx"> + Orthogonal Code</a></li> + <li><a href="http://codebetter.com/blogs/jeremy.miller/pages/129543.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/pages/129543.aspx"> + Dependency Inversion Principle</a></li> + <li><a href="http://www.artima.com/lejava/articles/designprinciples4.html" + mce_href="http://www.artima.com/lejava/articles/designprinciples4.html"> + Favor Composition over Inheritance</a></li> + </ul> + <p> + To sum it all up, well designed Object Oriented systems are <b>composed</b> of + many objects that work with each other to accomplish to goals of the system. + We want our systems to be decomposed into cohesive classes that perform a well + defined responsibility within the system, rather than monolithic “God” classes + that do too much. A cohesive class will have to be dependent upon other + classes to perform services outside of its own tightly defined responsibility. + In IoC speak, we call the collaborating objects <b>dependencies</b>. + </p> + <hr /> + <h2 class="style1"> + Dependencies</h2> + <p> + For example, in my current system we have a class called + <font face="Courier New">AddressEditController</font> that governs the creation + and editing of Address entities in our web based UI. The + AddressEditController needs to validate user input and persist or load data. + Those are two distinct responsibilities, so AddressEditController has + dependencies on other objects for these services. + </p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: rgb(43, 145, 175);">AddressEditController</span> : + <span style="color: rgb(43, 145, 175);">Controller</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: green;">// AddressEditController + uses IValidator to validate user input</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// and IRepository to + load and save Address information</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: blue;">readonly</span> + <span style="color: rgb(43, 145, 175);">IValidator</span> _validator;</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: rgb(43, 145, 175);">IRepository</span> _repository;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + So here’s some facts about <font face="Courier New">AddressEditController:</font></p> + <ul> + <li><font face="Courier New">AddressEditController</font> depends on + <font face="Courier New">IValidator</font> and <font face="Courier New"> + IRepository</font> </li> + <li><font face="Courier New">AddressEditController</font> cannot function unless it + has both an <font face="Courier New">IValidator</font> and an + <font face="Courier New">IRepository</font></li> + <li>From the concepts section above, for best results, the <font face="Courier New"> + AddressEditController</font> should be loosely coupled to its dependencies by + knowing as little about the inner workings of the real <font face="Courier New"> + IValidator</font> and <font face="Courier New">IRepository</font></li> + <li>The real IRepository is a Gateway into NHibernate. The concrete Repository class + cannot be used without its own dependency trail of external configuration, a + Singleton to keep track of an expensive resource, and some NHibernate + bootstrapping code. </li> + </ul> + <p> + Just calling a new() constructor on its dependencies isn’t the best design for + our <font face="Courier New">AddressEditController</font>. Creating a + concrete Validator class is very possible, but what if we want to selectively + replace the implementation of IValidator later? That’s only somewhat + likely, but the dependency on Repository is a much larger concern. I might + have semantic decoupling between <font face="Courier New">AddressEditController</font> + and Repository, but if <font face="Courier New">AddressEditController</font> + calls new Repository() itself, <font face="Courier New">AddressEditController</font> + will not be able to function without all that NHibernate bootstrapping. I + do not want a piece of my user interface to be tightly coupled to the existence + of the persistence layer. + </p> + <p> + In other scenarios, creating the dependencies may involve more than just calling + new() on the dependencies (don’t believe me? Go try to create an + HttpContext object).</p> + <p> + <font face="Courier New">AddressEditController</font> is responsible for the + workflow around editing Address entities in the UI. It shouldn’t be + concerned with NHibernate configuration and whatnot. One way to solve this + problem is to move the responsibility for building its dependencies to somewhere + external to <font face="Courier New">AddressEditController</font>. + </p> + <hr /> + <h2> + Inversion of Control and Dependency Injection</h2> + <p> + In many cases, I don’t want my classes to have to be aware of how their + dependencies are created or located. I don’t want controller classes to + even care that they’re using an object that is created via Microsoft’s Provider + infrastructure, or a Singleton, or needs configuration data. My class + should only know the public interfaces of its dependencies. I can make + that true by applying “<a + href="http://codebetter.com/blogs/jeremy.miller/archive/2005/09/20/132290.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/archive/2005/09/20/132290.aspx">Inversion + of Control</a>.” Instead of doing:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + AddressEditController()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _validator = + <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);"> + Validator</span>();</p> + <p style="margin: 0px;"> + _repository = + <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);"> + Repository</span>();</p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + where <font face="Courier New">AddressEditController</font> calls linearly + through to the constructors on Validator and Repository, we can invert the + control to make the creator of <font face="Courier New">AddressEditController</font> + responsible for building the dependencies and “pushing” them into + <font face="Courier New">AddressEditController</font>. + </p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: rgb(43, 145, 175);">AddressEditController</span> : + <span style="color: rgb(43, 145, 175);">Controller</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + </p> + <span style="color: blue;">private</span> <span style="color: blue;"> + readonly</span> <span style="color: rgb(43, 145, 175);">IValidator</span> + _validator; + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: rgb(43, 145, 175);">IRepository</span> _repository;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + AddressEditController(<span style="color: rgb(43, 145, 175);">IValidator</span> + validator, <span style="color: rgb(43, 145, 175);">IRepository</span> + repository)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _validator = validator;</p> + <p style="margin: 0px;"> + _repository = repository;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + The code sample above uses a form of Inversion of Control called + <a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx"> + Dependency Injection</a> to push in the dependencies via a constructor function. + Of course, at some point, something needs to know how to create the entire chain + of dependencies and do all of that Dependency Injection. StructureMap + supports a pattern known as + <a href="http://martinfowler.com/articles/injection.html#UsingAServiceLocator" + mce_href="http://martinfowler.com/articles/injection.html#UsingAServiceLocator"> + Service Locator</a>:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Creates an AddressEditController with all of its dependencies</span></p> + <p style="margin: 0px;"> + + <span style="color: rgb(43, 145, 175);">AddressEditController</span> controller + = <span style="color: rgb(43, 145, 175);">ObjectFactory</span>.GetInstance<<span + style="color: rgb(43, 145, 175);">AddressEditController</span>>();</p> + </div> + <p> + <font face="Courier New">ObjectFactory</font> is a StructureMap class that + serves as a well known place to go and find any service that you need. + When the <font face="Courier New">AddressEditController</font> is created and + returned by <font face="Courier New">ObjectFactory</font>, it should be + completely ready to go. There’s another important concept to understand + before you use StructureMap. + </p> + <hr /> + <h2> + Auto Wiring</h2> + <p> + Every "real" IoC container supports the concept of "Auto Wiring." Auto + Wiring simply means that StructureMap can figure out dependency chains for you + without a lot of explicit configuration. When you ask for + <font face="Courier New">AddressEditController</font>, there is more going on + than just <font face="Courier New">AddressEditController</font> and its two + dependencies. The Repository class itself has its own dependencies.</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + [<span style="color: rgb(43, 145, 175);">DefaultConstructor</span>]</p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> Repository(<span + style="color: rgb(43, 145, 175);">ISessionSource</span> source) : + <span style="color: blue;">this</span>(source.CreateSession())</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + In turn, the concrete version of <font face="Courier New">ISessionSource</font> + above has <b>its</b> own dependencies:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + SessionSource(<span style="color: rgb(43, 145, 175);">IDictionary</span><<span + style="color: blue;">string</span>, <span style="color: blue;">string</span>> + properties, <span style="color: rgb(43, 145, 175);">PersistenceModel</span> + model)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _configuration = + <span style="color: blue;">new</span> <span style="color: rgb(43, 145, 175);"> + Configuration</span>();</p> + <p style="margin: 0px;"> + + _configuration.AddProperties(properties);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + model.Configure(_configuration);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + _sessionFactory = + _configuration.BuildSessionFactory();</p> + <p style="margin: 0px;"> + }</p> + </div> + <p> + which starts to get interesting because <font face="Courier New">SessionSource</font> + needs some information like connection strings that have to come in from Xml + configuration: + </p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: blue;"><</span><span style="color: rgb(163, 21, 21);">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: rgb(163, 21, 21);">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;">ShadeTree.DomainModel.ISessionSource,ShadeTree.DomainModel</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;">ShadeTree.DomainModel.SessionSource,ShadeTree.DomainModel</span>"<span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">properties</span><span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">connection.provider</span>"<span style="color: blue;"> + </span><span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">NHibernate.Connection.DriverConnectionProvider</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">connection.driver_class</span>"<span + style="color: blue;"> </span><span style="color: red;">Value</span><span + style="color: blue;">=</span>"<span style="color: blue;">NHibernate.Driver.SqlClientDriver</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">dialect</span>"<span style="color: blue;"> </span> + <span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">NHibernate.Dialect.MsSql2000Dialect</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">hibernate.dialect</span>"<span style="color: blue;"> + </span><span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">NHibernate.Dialect.MsSql2000Dialect</span>"<span + style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">use_outer_join</span>"<span style="color: blue;"> + </span><span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">true</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">connection.connection_string</span>"<span + style="color: blue;"> </span><span style="color: red;">Value</span><span + style="color: blue;">=</span>"<span style="color: blue;">a connection string + that I’m certainly not giving out to you!</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> <</span><span + style="color: rgb(163, 21, 21);">Pair</span><span style="color: blue;"> + </span><span style="color: red;">Key</span><span style="color: blue;">=</span>"<span + style="color: blue;">show_sql</span>"<span style="color: blue;"> </span> + <span style="color: red;">Value</span><span style="color: blue;">=</span>"<span + style="color: blue;">true</span>"<span style="color: blue;"> /></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </</span><span + style="color: rgb(163, 21, 21);">properties</span><span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"> </</span><span + style="color: rgb(163, 21, 21);">DefaultInstance</span><span + style="color: blue;">></span></p> + <p style="margin: 0px;"> + <span style="color: blue;"></</span><span style="color: rgb(163, 21, 21);">StructureMap</span><span + style="color: blue;">></span></p> + </div> + <p> + Here’s some of the configuration for the other services that the entire + EditAddressController needs:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: rgb(43, 145, 175);">IValidator</span>>().TheDefaultIsConcreteType<<span + style="color: rgb(43, 145, 175);">Validator</span>>();</p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: rgb(43, 145, 175);">IRepository</span>>().TheDefaultIsConcreteType<<span + style="color: rgb(43, 145, 175);">Repository</span>>().CacheBy(<span + style="color: rgb(43, 145, 175);">InstanceScope</span>.Hybrid);</p> + <p style="margin: 0px;"> + ForRequestedType<<span + style="color: rgb(43, 145, 175);">PersistenceModel</span>>().TheDefaultIsConcreteType<<span + style="color: rgb(43, 145, 175);">DovetailPersistenceModel</span>>();</p> + </div> + <p> + At no point did I specify that <font face="Courier New">EditAddressController</font> + needs an <font face="Courier New">IRepository</font> that needs an + <font face="Courier New">ISessionSource</font> that needs 2-3 other things, but + yet when I call:</p> + <div style="border: thin solid black; background: white none repeat scroll 0% 50%; font-size: 10pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; color: black; font-family: courier new;"> + <p style="margin: 0px;"> + <span style="color: green;"> + // Creates an AddressEditController with all of its dependencies</span></p> + <p style="margin: 0px;"> + + <span style="color: rgb(43, 145, 175);">AddressEditController</span> controller + = <span style="color: rgb(43, 145, 175);">ObjectFactory</span>.GetInstance<<span + style="color: rgb(43, 145, 175);">AddressEditController</span>>();</p> + </div> + <p> + StructureMap will construct <font face="Courier New">EditAddressController</font> + that had a new instance of <font face="Courier New">Repository</font> that had a + new instance of <font face="Courier New">SessionSource</font> that had an + <font face="Courier New">IDictionary<string, string></font> object and a new + instance of <font face="Courier New">DovetailPersistenceModel</font>. I + don’t have to explicitly tell StructureMap to do that for me because it uses its + “Auto Wiring” feature to examine the dependencies of each concrete class and act + accordingly. StructureMap does need to know what to do with each type of + object it encounters. When it tries to build the <font face="Courier New"> + Repository</font> class StructureMap sees the constructor argument for + <font face="Courier New">ISessionSource</font> on <font face="Courier New"> + Repository</font>, and knows to build and inject a new <font face="Courier New"> + SessionSource</font> object (and so on as deep as you need to go).</p> + </body> </html> \ No newline at end of file Modified: trunk/Source/HTML/ConfiguringStructureMap.htm =================================================================== --- trunk/Source/HTML/ConfiguringStructureMap.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/ConfiguringStructureMap.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -15,7 +15,8 @@ else from the initial releases to StructureMap 2.5+. You have three forms of configuration to choose from:</p> <ol> - <li><a href="RegistryDSL.htm">Registry DSL</a> -- The programmatic Fluent Interface[LINK] API for configuring the Container in code.</li> + <li><a href="RegistryDSL.htm">Registry DSL</a> -- The programmatic + <a href="http://www.martinfowler.com/bliki/FluentInterface.html">Fluent Interface</a> API for configuring the Container in code.</li> <li><a href="XmlConfiguration.htm">Xml configuration</a> (StructureMap.config, the App.config file, or named files)</li> <li><a href="UsingAttributes.htm">StructureMap Attributes </a>-- Not fully deprecated, but not really recommended either. </li> </ol> Modified: trunk/Source/HTML/Default.htm =================================================================== --- trunk/Source/HTML/Default.htm 2009-01-04 02:55:42 UTC (rev 215) +++ trunk/Source/HTML/Default.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -10,7 +10,7 @@ <p> StructureMap is a <a href="http://www.martinfowler.com/articles/injection.html">Dependency - Injection</a> / Inversion of Control[LINK] tool for .Net that can be used to improve the architectural + Injection</a> / <a href="InversionOfControl.htm">Inversion of Control</a> tool for .Net that can be used to improve the architectural qualities of an object oriented system by reducing the mechanical costs of good design techniques. StructureMap can enable looser coupling between classes and their dependencies, improve the testability of a class structure, and provide @@ -40,25 +40,30 @@ <p>Do not use StructureMap if an application or process requires little flexibility. The abstraction and indirection afforded by StructureMap is unnecessary and even harmful in simpler systems or processes. </p> - <h3>Status</h3> + <p>The easiest way to get started is with the <a href="QuickStart.htm">StructureMap + QuickStart</a>. Please send any questions or suggestions to the + <a href="http://groups.google.com/group/structuremap-users/post?hl=en"> + StructureMap User Group</a> on Google Groups.</p> + <p> </p> + <h2>Status</h2> <p>StructureMap is the oldest IoC/DI tool for .Net development and has been used in multiple production systems since June 2004. The current version 2.5.2 was released in January 2009, with a - 2.6 release scheduled no later than the end of January 2009. StructureMap is + 2.6 release scheduled for no later than the end of January 2009. StructureMap is primarily maintained and developed by <a href="mailto:jer...@ya...?subject=StructureMap">Jeremy D. Miller</a>, <a href="http://codebetter.com/blogs/jeremy.miller">The - Shade Tree Developer</a> and Joshua Flanagan [LINK] with other contributions from + Shade Tree Developer</a> and + <a href="http://www.lostechies.com/blogs/joshuaflanagan/default.aspx">Joshua Flanagan</a> with other contributions from the community.</p> <hr /> - <h2> - <strong>Related Links:</strong></h2> + <h2>Related Links:</h2> <ul> <li><a href="http://flimflan.com/blog/HelloStructureMap.aspx">Hello StructureMap</a> </li> <li><a href="http://frickinsweet.com/ryanlanciaux.com/post/Very-Quick-and-Simple-Dependency-Injection-with-StructureMap.aspx"> Very Quick and Simple Dependency Injection with StructureMap</a> </li> - <li><a href="http://dimecasts.net/Casts/ByTag/StructureMap">StructureMap on + <li><a href="http://dimecasts.net/Casts/ByTag/StructureMap">StructureMap ScreenCasts on DimeCasts</a> </li> <li><a href="http://codebetter.com/blogs/jeremy.miller/archive/2008/10/25/initializing-and-configuring-a-structuremap-container.aspx"> Initializing and Configuring a StructureMap Container</a> </li> @@ -88,7 +93,7 @@ Integrating StructureMap with WCF</a> </li> </ul> - <p> </p> + <hr /> <p> </p> </body> Added: trunk/Source/HTML/DependencyInjection.htm =================================================================== --- trunk/Source/HTML/DependencyInjection.htm (rev 0) +++ trunk/Source/HTML/DependencyInjection.htm 2009-01-05 04:27:51 UTC (rev 216) @@ -0,0 +1,1076 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Dependency Injection - What is it, and what is it good for?</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> + <style type="text/css"> + .style1 + { + font-weight: normal; + } + </style> + </head> + <body> + + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + This was originally posted on + <a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/10/06/132825.aspx">Jeremy's blog</a> way back in 2005. A few things + have changed, specifically the possibility of using mocking tools that can mock + concrete classes and mock without using Dependency Injection (DI) -- but Jeremy + still thinks it's much cleaner to use DI ;-)</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + </p> + <h2 style="margin: 0in 0in 0pt;"> + Dependency Injection</h2> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + Dependency Injection is a specific usage of the larger + <a href="InversionOfControl.htm">Inversion of Control</a> concept.<span style=""> </span>In a nutshell, dependency injection + just means that a given class or system is no longer responsible for + instantiating their own dependencies.<span style=""> </span>In this case + “Inversion of Control” refers to moving the responsibility for locating and + attaching dependency objects to another class or a DI tool.<span style=""> + </span>That might not sound that terribly profound, but it opens the door for a + lot of interesting scenarios.</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + While there’s a fair amount of unnecessary buzz and hype about the concept, I’ve + found Dependency Injection to be very advantageous for doing Test Driven + Development without pulling your hair out.<span style=""> </span>If you’ve + seen articles or blog posts about Dependency Injection but don’t quite + internalize the value of DI yet, here are the facts as I see them:</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <ol style="margin-top: 0in;" type="1"> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Dependency Injection is an + important pattern for creating classes that are easier to unit test in isolation</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Promotes loose coupling between + classes and subsystems </li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Adds potential flexibility to a + codebase for future changes</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Can enable better code reuse</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;"><b style="">The implementation is + simple and does *not* require a fancy DI tool<o:p></o:p></b></li> + </ol> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + The <a href="http://picocontainer.org/" mce_href="http://picocontainer.org/"> + PicoContainer</a> team even has silly tee shirts printed up that say “I expected + a paradigm shift, but all I got was a lousy constructor function.”<span + style=""> </span>DI is certainly a case where a minimum of effort + supplies quite a bit of benefit.<span style=""> </span>Don’t blow it off + just because it seems trivial.<span style=""> </span> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + There are tools out there that do Dependency Injection in .Net.<span style=""> + </span>I use my own tool called <a href="http://structuremap.sourceforge.net/" + mce_href="http://structuremap.sourceforge.net/">StructureMap</a> in my + development, but I’m going to focus on only the concept of DI in this post.</p> + <hr /> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <h2 style="margin: 0in 0in 0pt;"> + <b style="">Example Problem<o:p></o:p></b></h2> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <b style=""><o:p> </o:p></b></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + My first experience with conscious usage of DI was a WinForms client + communicating with the backend via web services that was built with the + <a href="http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/articles/129546.aspx"> + Model View Presenter</a> (“Humble Dialog Box”) architecture for easier unit + testing.<span style=""> </span>Most screens in the client end up with + something like this set of classes:</p> + <ul style="margin-top: 0in;" type="disc"> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Model – Whatever business + object/DataSet/chunk of data is being displayed or edited</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">View – A WinForms UserControl + class.<span style=""> </span>Displays data to a user and captures user input + and screen events (duh).</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Service – A web service proxy + class to send requests to the backend</li> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Presenter – The controller class + that coordinates all of the above.</li> + </ul> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + The presenter class without Dependency Injection might look like this.</p> + <div class="code-sample"> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;">class</span> + Presenter<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">private</span> View _view;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">private</span> Model _model;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> Presenter(){}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;"> + object</span> CreateView(Model model)<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_model = model;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_view = <span style="color: blue;">new</span> View();<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_view.DisplayModel(model);<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">return</span> _view;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;">void</span> + Close()<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">bool</span> canClose = + <span style="color: blue;">true</span>;<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><o:p></o:p></span> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">if</span> (_view.IsDirty())<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>canClose = _view.CanCloseDirtyScreen();<span style=""> </span><o:p></o:p> + </span> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">if</span> (canClose)<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>_view.Close();<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><o:p> </o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span><span style="color: blue;">public</span> <span style="color: blue;">void</span> + Save()<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>{<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>Service service = <span style="color: blue;">new</span> Service();<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>service.Persist(_model);<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}<o:p></o:p></span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <span style="font-size: 10pt; font-family: 'Courier New';"><span style=""> + </span>}</span></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + +</div> + + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + </p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + This code cannot be unit tested in isolation because it has a tight coupling to + a concrete implementation of both the WinForms UserControl (View) and the proxy + class to a web service (Service).<span style=""> </span>This code as is + cannot function without both the User Interface and a web server running the + backend.<span style=""> </span>The point of using the MVP is to + isolate most of the user interface logic away from the WinForms and web service + mechanics to enable effective unit testing, so we’re missing something here.<span + style=""> </span>To unit test the presenter logic we’d like to replace + the user interface and web service dependencies with a + <a href="http://martinfowler.com/articles/mocksArentStubs.html" + mce_href="http://martinfowler.com/articles/mocksArentStubs.html">Mock</a> + object inside our test fixture classes.<span style=""> </span>In order to + mock the view and service, we first need to use the + <a href="http://codebetter.com/blogs/jeremy.miller/articles/129543.aspx" + mce_href="http://codebetter.com/blogs/jeremy.miller/articles/129543.aspx"> + Dependency Inversion Principle</a> to make the + <span style="font-family: 'Courier New';">Presenter</span> class depend on an + abstracted <span style="font-family: 'Courier New';">IView</span> and + <span style="font-family: 'Courier New';">IService</span> interface instead of + the concrete <span style="font-family: 'Courier New';">UserControl</span> and + <span style="font-family: 'Courier New';">WebProxy</span> classes.<span + style=""> </span>The next thing to do is to alter the + <span style="font-family: 'Courier New';">Presenter</span> class so that we can + substitute at run time the mock objects instead of the concrete classes within + the unit tests.<span style=""> </span>This is where Dependency Injection + comes into play.</p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + <o:p> </o:p></p> + <p class="MsoNormal" style="margin: 0in 0in 0pt;"> + There are a couple of different flavors of Dependency Injection (via + <a href="http://martinfowler.com/articles/injection.html" + mce_href="http://martinfowler.com/articles/injection.html">Martin Fowler</a> + + the Pico guys)</p> + <ol style="margin-top: 0in;" type="1"> + <li class="MsoNormal" style="margin: 0in 0in 0pt;">Constructor Injection – Attach + the dependencies through a constructor function at object creation</li> + <li class... [truncated message content] |
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] |
From: <jer...@us...> - 2009-01-03 00:07:37
|
Revision: 214 http://structuremap.svn.sourceforge.net/structuremap/?rev=214&view=rev Author: jeremydmiller Date: 2009-01-03 00:07:32 +0000 (Sat, 03 Jan 2009) Log Message: ----------- Missing Instance, BuildUp, documentation, conditional instance Modified Paths: -------------- trunk/Docs/style.css trunk/Source/CommonAssemblyInfo.cs trunk/Source/StructureMap/BuildSession.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceExpression.cs trunk/Source/StructureMap/Configuration/DSL/Registry.cs trunk/Source/StructureMap/ConfigurationExpression.cs trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/Emitting/ArgumentEmitter.cs trunk/Source/StructureMap/Emitting/BuildInstanceMethod.cs trunk/Source/StructureMap/Emitting/InstanceBuilderAssembly.cs trunk/Source/StructureMap/Emitting/Parameters/ParameterEmitter.cs trunk/Source/StructureMap/ExplicitArgsExpression.cs trunk/Source/StructureMap/Graph/Constructor.cs trunk/Source/StructureMap/Graph/Plugin.cs trunk/Source/StructureMap/Graph/PluginCache.cs trunk/Source/StructureMap/Graph/PluginFamily.cs trunk/Source/StructureMap/Graph/SetterPropertyCollection.cs trunk/Source/StructureMap/IContainer.cs trunk/Source/StructureMap/IInstanceFactory.cs trunk/Source/StructureMap/InitializationExpression.cs trunk/Source/StructureMap/InstanceBuilder.cs trunk/Source/StructureMap/InstanceFactory.cs trunk/Source/StructureMap/ObjectFactory.cs trunk/Source/StructureMap/Pipeline/BuildFrame.cs trunk/Source/StructureMap/ReflectionHelper.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap/SystemRegistry.cs trunk/Source/StructureMap.Testing/Configuration/DSL/AddInstanceTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/GenericFamilyExpressionTester.cs trunk/Source/StructureMap.Testing/Examples/RegisteringWithTheAPI.cs trunk/Source/StructureMap.Testing/Examples.cs trunk/Source/StructureMap.Testing/Graph/ContainerTester.cs trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs trunk/Source/StructureMap.Testing/Graph/PluginTester.cs trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs trunk/Source/StructureMap.Testing/Pipeline/OptionalSetterInjectionTester.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj trunk/Source/StructureMap.Testing.Widget/BuilderSamples.cs trunk/Source/StructureMap.Testing.Widget3/IService.cs trunk/cruise.build Added Paths: ----------- trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs trunk/Source/StructureMap/Emitting/BuildUpMethod.cs trunk/Source/StructureMap/Pipeline/ConditionalInstance.cs trunk/Source/StructureMap.Testing/AutoWiringExamples.cs trunk/Source/StructureMap.Testing/Bugs/SingletonShouldBeLazy.cs trunk/Source/StructureMap.Testing/BuildUpIntegratedTester.cs trunk/Source/StructureMap.Testing/BuildUpTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/ProgrammaticConstructorSelectionTester.cs trunk/Source/StructureMap.Testing/Examples/CustomInstance.cs trunk/Source/StructureMap.Testing/Graph/ConventionBasedSetterInjectionTester.cs trunk/Source/StructureMap.Testing/Pipeline/ConditionalInstanceTester.cs trunk/Source/StructureMap.Testing/Pipeline/MissingInstanceTester.cs trunk/Source/StructureMap.Testing/PrimitiveArrayTester.cs Modified: trunk/Docs/style.css =================================================================== --- trunk/Docs/style.css 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Docs/style.css 2009-01-03 00:07:32 UTC (rev 214) @@ -16,7 +16,8 @@ } H2 { - COLOR: #316592; + BACKGROUND-COLOR: #316592; + COLOR: white; FONT-FAMILY: Arial; FONT-SIZE: large; FONT-WEIGHT: bold; Modified: trunk/Source/CommonAssemblyInfo.cs =================================================================== --- trunk/Source/CommonAssemblyInfo.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/CommonAssemblyInfo.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -5,7 +5,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:2.0.50727.1434 +// Runtime Version:2.0.50727.3053 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. Modified: trunk/Source/StructureMap/BuildSession.cs =================================================================== --- trunk/Source/StructureMap/BuildSession.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/BuildSession.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -25,6 +25,24 @@ /// <typeparam name="T"></typeparam> /// <returns></returns> T GetInstance<T>(); + + /// <summary> + /// Gets the root "frame" of the object request + /// </summary> + BuildFrame Root { get; } + + /// <summary> + /// The requested instance name of the object graph + /// </summary> + string RequestedName { get; } + + /// <summary> + /// Register a default object for the given PluginType that will + /// be used throughout the rest of the current object request + /// </summary> + /// <param name="pluginType"></param> + /// <param name="defaultObject"></param> + void RegisterDefault(Type pluginType, object defaultObject); } public class BuildSession : IContext @@ -63,6 +81,8 @@ } + public string RequestedName { get; set; } + protected PipelineGraph pipelineGraph { get { return _pipelineGraph; } @@ -85,6 +105,11 @@ return (T) CreateInstance(typeof (T)); } + BuildFrame IContext.Root + { + get { return _buildStack.Root; } + } + #endregion public virtual object CreateInstance(Type pluginType, string name) @@ -112,6 +137,7 @@ return result; } + public virtual Array CreateInstanceArray(Type pluginType, Instance[] instances) { Array array; Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/CreatePluginFamilyExpression.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -38,6 +38,14 @@ get { return new InstanceExpression<PLUGINTYPE>(i => registerDefault(i)); } } + public InstanceExpression<PLUGINTYPE> MissingNamedInstanceIs + { + get + { + return new InstanceExpression<PLUGINTYPE>(i => _alterations.Add(family => family.MissingInstance = i)); + } + } + /// <summary> /// Add multiple Instance's to this PluginType /// </summary> Modified: trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceExpression.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceExpression.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Configuration/DSL/Expressions/InstanceExpression.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -28,6 +28,11 @@ LiteralInstance IsThis(T obj); } + public interface ThenItExpression<T> + { + IsExpression<T> ThenIt { get; } + } + /// <summary> /// An Expression Builder to define Instances of a PluginType. /// This is mostly used for configuring open generic types @@ -178,9 +183,17 @@ /// <param name="url"></param> /// <returns></returns> UserControlInstance LoadControlFrom(string url); + + /// <summary> + /// Creates an Instance according to conditional rules + /// </summary> + /// <param name="configuration"></param> + /// <returns></returns> + // Conditional object construction + ConditionalInstance<T> Conditional(Action<ConditionalInstance<T>.ConditionalInstanceExpression<T>> configuration); } - public class InstanceExpression<T> : IInstanceExpression<T> + public class InstanceExpression<T> : IInstanceExpression<T>, ThenItExpression<T> { private readonly Action<Instance> _action; @@ -268,5 +281,15 @@ { return returnInstance(new UserControlInstance(url)); } + + public ConditionalInstance<T> Conditional(Action<ConditionalInstance<T>.ConditionalInstanceExpression<T>> configuration) + { + return returnInstance(new ConditionalInstance<T>(configuration)); + } + + IsExpression<T> ThenItExpression<T>.ThenIt + { + get { return this; } + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Configuration/DSL/Registry.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Configuration/DSL/Registry.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -7,6 +7,37 @@ namespace StructureMap.Configuration.DSL { + public interface IRegistry + { + // Registering Types -- BuildInstancesOf() and ForRequestedType() are Synonyms + CreatePluginFamilyExpression<PLUGINTYPE> BuildInstancesOf<PLUGINTYPE>(); + CreatePluginFamilyExpression<PLUGINTYPE> ForRequestedType<PLUGINTYPE>(); + + GenericFamilyExpression ForRequestedType(Type pluginType); + + // Shortcut for configuring the default configuration of a concrete type + Registry.BuildWithExpression<T> ForConcreteType<T>(); + + // Adding additional Instances of a PluginType + IsExpression<T> InstanceOf<T>(); + GenericIsExpression InstanceOf(Type pluginType); + + // Creating or Adding to a Profile + ProfileExpression CreateProfile(string profileName); + void CreateProfile(string profileName, Action<ProfileExpression> action); + + // Interception + void RegisterInterceptor(TypeInterceptor interceptor); + MatchedTypeInterceptor IfTypeMatches(Predicate<Type> match); + + // Type Scanning and Auto Registration + void Scan(Action<IAssemblyScanner> action); + + // Controlling Setter Injection Behavior + CreatePluginFamilyExpression<PLUGINTYPE> FillAllPropertiesOfType<PLUGINTYPE>(); + void SetAllProperties(Action<SetterConvention> action); + } + /// <summary> /// A Registry class provides methods and grammars for configuring a Container or ObjectFactory. /// Using a Registry subclass is the recommended way of configuring a StructureMap Container. @@ -20,7 +51,7 @@ /// } /// } /// </example> - public class Registry + public class Registry : IRegistry { private readonly List<Action<PluginGraph>> _actions = new List<Action<PluginGraph>>(); private readonly List<Action> _basicActions = new List<Action>(); @@ -79,7 +110,6 @@ /// Scoping, the Default Instance, and interception. This method is specifically /// meant for registering open generic types /// </summary> - /// <typeparam name="PLUGINTYPE"></typeparam> /// <returns></returns> public GenericFamilyExpression ForRequestedType(Type pluginType) { @@ -182,6 +212,11 @@ internal static bool IsPublicRegistry(Type type) { + if (type.Assembly == typeof(Registry).Assembly) + { + return false; + } + if (!typeof (Registry).IsAssignableFrom(type)) { return false; @@ -291,5 +326,16 @@ } #endregion + + /// <summary> + /// Creates automatic "policies" for which public setters are considered mandatory + /// properties by StructureMap that will be "setter injected" as part of the + /// construction process. + /// </summary> + /// <param name="action"></param> + public void SetAllProperties(Action<SetterConvention> action) + { + action(new SetterConvention()); + } } } \ No newline at end of file Added: trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs =================================================================== --- trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs (rev 0) +++ trunk/Source/StructureMap/Configuration/DSL/SetterConvention.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -0,0 +1,63 @@ +using System; +using System.Reflection; +using StructureMap.Graph; +using StructureMap; + +namespace StructureMap.Configuration.DSL +{ + /// <summary> + /// Used as an expression builder to specify setter injection policies + /// </summary> + public class SetterConvention + { + /// <summary> + /// Directs StructureMap to treat all public setters of type T as + /// mandatory properties + /// </summary> + /// <typeparam name="T"></typeparam> + public void OfType<T>() + { + Matching(prop => prop.PropertyType == typeof (T)); + } + + /// <summary> + /// Directs StructureMap to treat all public setters that match the + /// rule as mandatory properties + /// </summary> + /// <param name="rule"></param> + public void Matching(Predicate<PropertyInfo> rule) + { + PluginCache.UseSetterRule(rule); + } + + /// <summary> + /// Directs StructureMap to treat all public setters with a property + /// type in the specified namespace as mandatory properties + /// </summary> + /// <param name="nameSpace"></param> + public void WithAnyTypeFromNamespace(string nameSpace) + { + Matching(prop => prop.PropertyType.IsInNamespace(nameSpace)); + } + + /// <summary> + /// Directs StructureMap to treat all public setters with a property + /// type in the specified namespace as mandatory properties + /// </summary> + /// <typeparam name="T"></typeparam> + public void WithAnyTypeFromNamespaceContainingType<T>() + { + WithAnyTypeFromNamespace(typeof(T).Namespace); + } + + /// <summary> + /// Directs StructureMap to treat all public setters where to property name + /// matches the specified rule as a mandatory property + /// </summary> + /// <param name="rule"></param> + public void NameMatches(Predicate<string> rule) + { + Matching(prop => rule(prop.Name)); + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/ConfigurationExpression.cs =================================================================== --- trunk/Source/StructureMap/ConfigurationExpression.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/ConfigurationExpression.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Xml; using StructureMap.Configuration; using StructureMap.Configuration.DSL; @@ -83,5 +85,20 @@ return builder.Build(); } + + /// <summary> + /// Use to programmatically select the constructor function of a concrete + /// class. Applies globally to all Containers in a single AppDomain. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="func"></param> + public void SelectConstructor<T>(Expression<Func<T>> expression) + { + PluginCache.GetPlugin(typeof (T)).UseConstructor(expression); + } } + + + + } \ No newline at end of file Modified: trunk/Source/StructureMap/Container.cs =================================================================== --- trunk/Source/StructureMap/Container.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Container.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -40,7 +40,6 @@ /// </summary> /// <param name="pluginGraph">PluginGraph containing the instance and type definitions /// for the Container</param> - /// <param name="failOnException">Flags the Container to fail or trap exceptions</param> public Container(PluginGraph pluginGraph) { construct(pluginGraph); @@ -80,7 +79,6 @@ /// <summary> /// Creates a new instance of the requested type T using the supplied Instance. Mostly used internally /// </summary> - /// <param name="pluginType"></param> /// <param name="instance"></param> /// <returns></returns> public T GetInstance<T>(Instance instance) @@ -91,7 +89,6 @@ /// <summary> /// Gets the default instance of the pluginType using the explicitly configured arguments from the "args" /// </summary> - /// <param name="pluginType"></param> /// <param name="args"></param> /// <returns></returns> public PLUGINTYPE GetInstance<PLUGINTYPE>(ExplicitArguments args) @@ -117,7 +114,7 @@ BasicInstance basicInstance = defaultInstance as BasicInstance; Instance instance = basicInstance == null ? defaultInstance : new ExplicitInstance(pluginType, args, basicInstance); - BuildSession session = withNewSession(); + BuildSession session = withNewSession(Plugin.DEFAULT); args.RegisterDefaults(session); @@ -128,12 +125,12 @@ /// <summary> /// Gets all configured instances of type T using explicitly configured arguments from the "args" /// </summary> - /// <typeparam name="T"></typeparam> + /// <param name="type"></param> /// <param name="args"></param> /// <returns></returns> public IList GetAllInstances(Type type, ExplicitArguments args) { - BuildSession session = withNewSession(); + BuildSession session = withNewSession(Plugin.DEFAULT); args.RegisterDefaults(session); @@ -143,7 +140,7 @@ public IList<T> GetAllInstances<T>(ExplicitArguments args) { - BuildSession session = withNewSession(); + BuildSession session = withNewSession(Plugin.DEFAULT); args.RegisterDefaults(session); @@ -185,7 +182,7 @@ /// </summary> /// <typeparam name="T"></typeparam> /// <param name="name"></param> - /// <param name="instance"></param> + /// <param name="stub"></param> public void Inject<T>(string name, T stub) { LiteralInstance instance = new LiteralInstance(stub).WithName(name); @@ -199,7 +196,7 @@ /// <returns></returns> public IList<T> GetAllInstances<T>() { - BuildSession session = withNewSession(); + BuildSession session = withNewSession(Plugin.DEFAULT); return getListOfTypeWithSession<T>(session); } @@ -220,7 +217,7 @@ /// <returns></returns> public object GetInstance(Type pluginType, string instanceKey) { - return withNewSession().CreateInstance(pluginType, instanceKey); + return withNewSession(instanceKey).CreateInstance(pluginType, instanceKey); } /// <summary> @@ -228,7 +225,6 @@ /// </summary> /// <param name="pluginType"></param> /// <param name="instanceKey"></param> - /// <param name="instance"></param> /// <returns></returns> public object TryGetInstance(Type pluginType, string instanceKey) { @@ -241,7 +237,6 @@ /// Creates or finds the default instance of the pluginType. Returns null if the pluginType is not known to the container. /// </summary> /// <param name="pluginType"></param> - /// <param name="instance"></param> /// <returns></returns> public object TryGetInstance(Type pluginType) { @@ -254,7 +249,6 @@ /// Creates or finds the default instance of type T. Returns the default value of T if it is not known to the container. /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="instance"></param> /// <returns></returns> public T TryGetInstance<T>() { @@ -262,10 +256,25 @@ } /// <summary> + /// The "BuildUp" method takes in an already constructed object + /// and uses Setter Injection to push in configured dependencies + /// of that object + /// </summary> + /// <param name="target"></param> + public void BuildUp(object target) + { + var pluggedType = target.GetType(); + IConfiguredInstance instance = _pipelineGraph.GetDefault(pluggedType) as IConfiguredInstance + ?? new ConfiguredInstance(pluggedType); + + var builder = PluginCache.FindBuilder(pluggedType); + builder.BuildUp(instance, withNewSession(Plugin.DEFAULT), target); + } + + /// <summary> /// Creates or finds the named instance of type T. Returns the default value of T if the named instance is not known to the container. /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="instance"></param> /// <returns></returns> public T TryGetInstance<T>(string instanceKey) { @@ -279,7 +288,7 @@ /// <returns></returns> public object GetInstance(Type pluginType) { - return withNewSession().CreateInstance(pluginType); + return withNewSession(Plugin.DEFAULT).CreateInstance(pluginType); } @@ -291,7 +300,7 @@ /// <returns></returns> public object GetInstance(Type pluginType, Instance instance) { - return withNewSession().CreateInstance(pluginType, instance); + return withNewSession(instance.Name).CreateInstance(pluginType, instance); } public void SetDefault(Type pluginType, Instance instance) @@ -343,7 +352,7 @@ /// <returns></returns> public IList GetAllInstances(Type pluginType) { - return forType(pluginType).GetAllInstances(withNewSession()); + return forType(pluginType).GetAllInstances(withNewSession(Plugin.DEFAULT)); } /// <summary> @@ -464,9 +473,9 @@ _pipelineGraph.SetDefault(pluginType, instance); } - private BuildSession withNewSession() + private BuildSession withNewSession(string name) { - return new BuildSession(_pipelineGraph, _interceptorLibrary); + return new BuildSession(_pipelineGraph, _interceptorLibrary){RequestedName = name}; } @@ -474,5 +483,7 @@ { return _pipelineGraph.ForType(type); } + + } } \ No newline at end of file Modified: trunk/Source/StructureMap/Emitting/ArgumentEmitter.cs =================================================================== --- trunk/Source/StructureMap/Emitting/ArgumentEmitter.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Emitting/ArgumentEmitter.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -13,11 +13,13 @@ private readonly PrimitiveParameterEmitter _primitive = new PrimitiveParameterEmitter(); private readonly StringParameterEmitter _string = new StringParameterEmitter(); private readonly ILGenerator ilgen; + private readonly bool _inConstructor = true; - public ArgumentEmitter(ILGenerator ilgen) + public ArgumentEmitter(ILGenerator ilgen, bool inConstructor) { this.ilgen = ilgen; + _inConstructor = inConstructor; } #region IArgumentVisitor Members @@ -82,7 +84,7 @@ } else { - emitter.OptionalSetter(ilgen, property); + emitter.OptionalSetter(ilgen, property, _inConstructor); } } } Modified: trunk/Source/StructureMap/Emitting/BuildInstanceMethod.cs =================================================================== --- trunk/Source/StructureMap/Emitting/BuildInstanceMethod.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Emitting/BuildInstanceMethod.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -47,7 +47,7 @@ ilgen.DeclareLocal(typeof (bool)); } - var arguments = new ArgumentEmitter(ilgen); + var arguments = new ArgumentEmitter(ilgen, true); _plugin.VisitConstructor(arguments); Added: trunk/Source/StructureMap/Emitting/BuildUpMethod.cs =================================================================== --- trunk/Source/StructureMap/Emitting/BuildUpMethod.cs (rev 0) +++ trunk/Source/StructureMap/Emitting/BuildUpMethod.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection.Emit; +using System.Text; +using StructureMap.Graph; +using StructureMap.Pipeline; + +namespace StructureMap.Emitting +{ + public class BuildUpMethod : Method + { + private readonly Plugin _plugin; + + public BuildUpMethod(Plugin plugin) + { + _plugin = plugin; + } + + public override string MethodName + { + get { return "BuildUp"; } + } + + public override Type[] ArgumentList + { + get { return new Type[] { typeof(IConfiguredInstance), typeof(BuildSession) , typeof(object)}; } + } + + public override Type ReturnType + { + get { return typeof(void); } + } + + protected override void Generate(ILGenerator ilgen) + { + ilgen.Emit(OpCodes.Nop); + + ilgen.DeclareLocal(_plugin.PluggedType); + ilgen.DeclareLocal(typeof(bool)); + + ilgen.Emit(OpCodes.Ldarg_3); + ilgen.Emit(OpCodes.Castclass, _plugin.PluggedType); + ilgen.Emit(OpCodes.Stloc_0); + + var arguments = new ArgumentEmitter(ilgen, false); + + _plugin.VisitSetters(arguments); + + ilgen.Emit(OpCodes.Ret); + + } + } +} Modified: trunk/Source/StructureMap/Emitting/InstanceBuilderAssembly.cs =================================================================== --- trunk/Source/StructureMap/Emitting/InstanceBuilderAssembly.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Emitting/InstanceBuilderAssembly.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -88,8 +88,11 @@ { builderClass.AddPluggedTypeGetter(plugin.PluggedType); - var method = new BuildInstanceMethod(plugin); - builderClass.AddMethod(method); + var buildInstanceMethod = new BuildInstanceMethod(plugin); + builderClass.AddMethod(buildInstanceMethod); + + var buildUpMethod = new BuildUpMethod(plugin); + builderClass.AddMethod(buildUpMethod); } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Emitting/Parameters/ParameterEmitter.cs =================================================================== --- trunk/Source/StructureMap/Emitting/Parameters/ParameterEmitter.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Emitting/Parameters/ParameterEmitter.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -29,24 +29,30 @@ public abstract void MandatorySetter(ILGenerator ilgen, PropertyInfo property); - public void OptionalSetter(ILGenerator ilgen, PropertyInfo property) + public void OptionalSetter(ILGenerator ilgen, PropertyInfo property, bool inConstructor) { ilgen.Emit(OpCodes.Ldarg_1); ilgen.Emit(OpCodes.Ldstr, property.Name); ilgen.Emit(OpCodes.Callvirt, Methods.HAS_PROPERTY); ilgen.Emit(OpCodes.Ldc_I4_0); ilgen.Emit(OpCodes.Ceq); - ilgen.Emit(OpCodes.Stloc_2); - ilgen.Emit(OpCodes.Ldloc_2); + if (inConstructor) + { + ilgen.Emit(OpCodes.Stloc_2); + ilgen.Emit(OpCodes.Ldloc_2); + } + else + { + ilgen.Emit(OpCodes.Stloc_1); + ilgen.Emit(OpCodes.Ldloc_1); + } + + Label label = ilgen.DefineLabel(); - ilgen.Emit(OpCodes.Brtrue_S, label); - MandatorySetter(ilgen, property); - ilgen.Emit(OpCodes.Nop); - ilgen.MarkLabel(label); } } Modified: trunk/Source/StructureMap/ExplicitArgsExpression.cs =================================================================== --- trunk/Source/StructureMap/ExplicitArgsExpression.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/ExplicitArgsExpression.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -85,7 +85,6 @@ /// Gets all configured instances of type T using explicitly configured arguments /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="args"></param> /// <returns></returns> public IList<T> GetAllInstances<T>() { Modified: trunk/Source/StructureMap/Graph/Constructor.cs =================================================================== --- trunk/Source/StructureMap/Graph/Constructor.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Graph/Constructor.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -1,11 +1,12 @@ using System; +using System.Linq.Expressions; using System.Reflection; namespace StructureMap.Graph { public class Constructor : TypeRules { - private readonly ConstructorInfo _ctor; + private ConstructorInfo _ctor; private readonly Type _pluggedType; public Constructor(Type pluggedType) @@ -120,5 +121,19 @@ { return _ctor != null; } + + public void UseConstructor(Expression expression) + { + var finder = new ConstructorFinderVisitor(); + finder.Visit(expression); + + var ctor = finder.Constructor; + if (ctor == null) + { + throw new ApplicationException("Not a valid constructor function"); + } + + _ctor = ctor; + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/Plugin.cs =================================================================== --- trunk/Source/StructureMap/Graph/Plugin.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Graph/Plugin.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Reflection; using StructureMap.Pipeline; @@ -154,15 +155,14 @@ return templatedPlugin; } - public void SetFilledTypes(IList<Type> types) + public void UseConstructor(Expression expression) { - foreach (SetterProperty setter in _setters) - { - if (types.Contains(setter.Property.PropertyType)) - { - setter.IsMandatory = true; - } - } + _constructor.UseConstructor(expression); } + + public void UseSetterRule(Predicate<PropertyInfo> rule) + { + _setters.UseSetterRule(rule); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/PluginCache.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginCache.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Graph/PluginCache.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using StructureMap.Emitting; using StructureMap.Util; @@ -9,16 +10,27 @@ public static class PluginCache { private static readonly Cache<Type, InstanceBuilder> _builders; - private static readonly List<Type> _filledTypes = new List<Type>(); private static readonly Cache<Type, Plugin> _plugins; + private static readonly List<Predicate<PropertyInfo>> _setterRules; static PluginCache() { - _plugins = new Cache<Type, Plugin>(t => new Plugin(t)); + _setterRules = new List<Predicate<PropertyInfo>>(); + _plugins = new Cache<Type, Plugin>(t => + { + var plugin = new Plugin(t); + foreach (var rule in _setterRules) + { + plugin.UseSetterRule(rule); + } + + return plugin; + }); + + _builders = new Cache<Type, InstanceBuilder>(t => { Plugin plugin = _plugins[t]; - plugin.SetFilledTypes(_filledTypes); return new InstanceBuilderAssembly(new[] {plugin}).Compile()[0]; }); } @@ -45,11 +57,6 @@ private static void createAndStoreBuilders(IEnumerable<Plugin> plugins) { - foreach (Plugin plugin in plugins) - { - plugin.SetFilledTypes(_filledTypes); - } - var assembly = new InstanceBuilderAssembly(plugins); assembly.Compile().ForEach(b => _builders[b.PluggedType] = b); } @@ -68,6 +75,7 @@ { lock (typeof (PluginCache)) { + _setterRules.Clear(); _builders.Clear(); _plugins.Clear(); } @@ -75,7 +83,14 @@ public static void AddFilledType(Type type) { - _filledTypes.Add(type); + Predicate<PropertyInfo> predicate = prop => prop.PropertyType == type; + UseSetterRule(predicate); } + + public static void UseSetterRule(Predicate<PropertyInfo> predicate) + { + _setterRules.Add(predicate); + _plugins.Each(plugin => plugin.UseSetterRule(predicate)); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/PluginFamily.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginFamily.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Graph/PluginFamily.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -371,6 +371,8 @@ set { _defaultKey = value ?? string.Empty; } } + public Instance MissingInstance { get; set; } + #endregion } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/SetterPropertyCollection.cs =================================================================== --- trunk/Source/StructureMap/Graph/SetterPropertyCollection.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Graph/SetterPropertyCollection.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -125,5 +125,10 @@ return null; } + + public void UseSetterRule(Predicate<PropertyInfo> rule) + { + _properties.FindAll(setter => rule(setter.Property)).ForEach(setter => setter.IsMandatory = true); + } } } \ No newline at end of file Modified: trunk/Source/StructureMap/IContainer.cs =================================================================== --- trunk/Source/StructureMap/IContainer.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/IContainer.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -57,7 +57,6 @@ /// <summary> /// Creates a new instance of the requested type T using the supplied Instance. Mostly used internally /// </summary> - /// <param name="pluginType"></param> /// <param name="instance"></param> /// <returns></returns> T GetInstance<T>(Instance instance); @@ -81,7 +80,6 @@ /// </summary> /// <param name="pluginType"></param> /// <param name="instanceKey"></param> - /// <param name="instance"></param> /// <returns></returns> object TryGetInstance(Type pluginType, string instanceKey); @@ -89,7 +87,6 @@ /// Creates or finds the default instance of the pluginType. Returns null if the pluginType is not known to the container. /// </summary> /// <param name="pluginType"></param> - /// <param name="instance"></param> /// <returns></returns> object TryGetInstance(Type pluginType); @@ -97,7 +94,6 @@ /// Creates or finds the default instance of type T. Returns the default value of T if it is not known to the container. /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="instance"></param> /// <returns></returns> T TryGetInstance<T>(); @@ -105,7 +101,6 @@ /// Creates or finds the named instance of type T. Returns the default value of T if the named instance is not known to the container. /// </summary> /// <typeparam name="T"></typeparam> - /// <param name="instance"></param> /// <returns></returns> T TryGetInstance<T>(string instanceKey); @@ -183,11 +178,9 @@ /// <summary> /// Gets the default instance of type T using the explicitly configured arguments from the "args" /// </summary> - /// <typeparam name="T"></typeparam> + /// <param name="type"></param> /// <param name="args"></param> /// <returns></returns> - - IList GetAllInstances(Type type, ExplicitArguments args); T GetInstance<T>(ExplicitArguments args); @@ -222,5 +215,15 @@ /// </summary> /// <typeparam name="T"></typeparam> void EjectAllInstancesOf<T>(); + + /// <summary> + /// The "BuildUp" method takes in an already constructed object + /// and uses Setter Injection to push in configured dependencies + /// of that object + /// </summary> + /// <param name="target"></param> + void BuildUp(object target); + + void SetDefault(Type pluginType, Instance instance); } } \ No newline at end of file Modified: trunk/Source/StructureMap/IInstanceFactory.cs =================================================================== --- trunk/Source/StructureMap/IInstanceFactory.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/IInstanceFactory.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -14,6 +14,7 @@ Type PluginType { get; } IEnumerable<IInstance> Instances { get; } IBuildPolicy Policy { get; } + Instance MissingInstance { get; set; } void AddInstance(Instance instance); Instance AddType<T>(); Modified: trunk/Source/StructureMap/InitializationExpression.cs =================================================================== --- trunk/Source/StructureMap/InitializationExpression.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/InitializationExpression.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -166,6 +166,14 @@ /// <typeparam name="PLUGINTYPE"></typeparam> /// <returns></returns> CreatePluginFamilyExpression<PLUGINTYPE> FillAllPropertiesOfType<PLUGINTYPE>(); + + /// <summary> + /// Creates automatic "policies" for which public setters are considered mandatory + /// properties by StructureMap that will be "setter injected" as part of the + /// construction process. + /// </summary> + /// <param name="action"></param> + void SetAllProperties(Action<SetterConvention> action); } public class InitializationExpression : ConfigurationExpression, IInitializationExpression @@ -178,7 +186,14 @@ public bool UseDefaultStructureMapConfigFile { - set { _parserBuilder.UseAndEnforceExistenceOfDefaultFile = value; } + set + { + _parserBuilder.UseAndEnforceExistenceOfDefaultFile = value; + if (!value) + { + _parserBuilder.IgnoreDefaultFile = true; + } + } } public bool IgnoreStructureMapConfig Modified: trunk/Source/StructureMap/InstanceBuilder.cs =================================================================== --- trunk/Source/StructureMap/InstanceBuilder.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/InstanceBuilder.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -11,10 +11,13 @@ { private Container _manager; + // DO NOT ELIMINATE THIS METHOD public InstanceBuilder(){} public abstract Type PluggedType { get; } public abstract object BuildInstance(IConfiguredInstance instance, BuildSession session); + + public virtual void BuildUp(IConfiguredInstance instance, BuildSession session, object target) { } } } \ No newline at end of file Modified: trunk/Source/StructureMap/InstanceFactory.cs =================================================================== --- trunk/Source/StructureMap/InstanceFactory.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/InstanceFactory.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -17,6 +17,7 @@ private readonly Type _pluginType; private IBuildPolicy _policy = new BuildPolicy(); + #region constructor functions @@ -40,8 +41,8 @@ _policy = family.Policy; _pluginType = family.PluginType; + MissingInstance = family.MissingInstance; - family.EachInstance(AddInstance); } catch (StructureMapException) @@ -74,6 +75,8 @@ #region IInstanceFactory Members + public Instance MissingInstance { get; set; } + public Type PluginType { get { return _pluginType; } @@ -132,7 +135,7 @@ public Instance FindInstance(string name) { - return _instances[name]; + return _instances[name] ?? MissingInstance; } public void ImportFrom(PluginFamily family) Modified: trunk/Source/StructureMap/ObjectFactory.cs =================================================================== --- trunk/Source/StructureMap/ObjectFactory.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/ObjectFactory.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -417,5 +417,16 @@ return container.TryGetInstance<T>(instanceKey); } + /// <summary> + /// The "BuildUp" method takes in an already constructed object + /// and uses Setter Injection to push in configured dependencies + /// of that object + /// </summary> + /// <param name="target"></param> + public static void BuildUp(object target) + { + container.BuildUp(target); + } + } } \ No newline at end of file Modified: trunk/Source/StructureMap/Pipeline/BuildFrame.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/BuildFrame.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/Pipeline/BuildFrame.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -2,12 +2,31 @@ namespace StructureMap.Pipeline { + public interface IBuildFrame + { + /// <summary> + /// The requested PluginType of the Instance being create + /// </summary> + Type RequestedType { get; } + + /// <summary> + /// The Name of the Instance being created + /// </summary> + string Name { get; } + + /// <summary> + /// The actual ConcreteType being created. This will not always + /// be available + /// </summary> + Type ConcreteType { get; } + } + /// <summary> /// Models the current place in an object graph during the construction of /// an instance. Provides contextual information that can be used /// to alter the desired construction of child objects /// </summary> - public class BuildFrame + public class BuildFrame : IBuildFrame { private readonly Type _concreteType; private readonly string _name; Added: trunk/Source/StructureMap/Pipeline/ConditionalInstance.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/ConditionalInstance.cs (rev 0) +++ trunk/Source/StructureMap/Pipeline/ConditionalInstance.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using StructureMap.Configuration.DSL.Expressions; + +namespace StructureMap.Pipeline +{ + public class ConditionalInstance<T> : ExpressedInstance<ConditionalInstance<T>> + { + // Conditional Instance keeps track of zero or more internal Instance + // objects against a Predicate<IContext> condition + private readonly List<InstanceCase> _cases = new List<InstanceCase>(); + + // The "default" Instance to use if none of the conditional predicates + // are met. If this is not explicitly defined, the ConditionalInstance + // will simply look for the default Instance of the desired + // PluginType + public Instance _default = new DefaultInstance(); + + + public ConditionalInstance(Action<ConditionalInstanceExpression<T>> action) + { + action(new ConditionalInstanceExpression<T>(this)); + } + + protected override string getDescription() + { + return "Conditional Instance of " + typeof (T).FullName; + } + + protected override object build(Type pluginType, BuildSession session) + { + // Find the first InstanceCase that matches the BuildSession/IContext + var instanceCase = _cases.Find(c => c.Predicate(session)); + + // Use the Instance from the InstanceCase if it exists, + // otherwise, use the "default" + var instance = instanceCase == null ? _default : instanceCase.Instance; + + // delegate to the chosen Instance + return instance.Build(pluginType, session); + } + + public class ConditionalInstanceExpression<T> + { + private readonly ConditionalInstance<T> _parent; + + public ConditionalInstanceExpression(ConditionalInstance<T> parent) + { + _parent = parent; + } + + public ThenItExpression<T> If(Predicate<IContext> predicate) + { + return new InstanceExpression<T>(i => + { + var theCase = new InstanceCase() {Instance = i, Predicate = predicate}; + _parent._cases.Add(theCase); + }); + } + + public IsExpression<T> TheDefault + { + get + { + return new InstanceExpression<T>(i => _parent._default = i); + } + } + + + } + + protected override ConditionalInstance<T> thisInstance + { + get { return this; } + } + } + + public class InstanceCase + { + public Predicate<IContext> Predicate { get; set; } + public Instance Instance { get; set; } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/ReflectionHelper.cs =================================================================== --- trunk/Source/StructureMap/ReflectionHelper.cs 2009-01-02 23:58:17 UTC (rev 213) +++ trunk/Source/StructureMap/ReflectionHelper.cs 2009-01-03 00:07:32 UTC (rev 214) @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; using System.Linq.Expressions; using System.Reflection; @@ -58,4 +61,407 @@ return methodCall.Method; } } + + /// <summary> + /// Provides virtual methods that can be used by subclasses to parse an expression tree. + /// </summary> + /// <remarks> + /// This class actually already exists in the System.Core assembly...as an internal class. + /// I can only speculate as to why it is internal, but it is obviously much too dangerous + /// for anyone outside of Microsoft to be using... + /// </remarks> + [DebuggerStepThrough, DebuggerNonUserCode] + public abstract class ExpressionVisitorBase + { + public virtual Expression Visit(Expression exp) + { + if (exp == null) return exp; + + switch (exp.NodeType) + { + case ExpressionType.Negate: + case ExpressionType.NegateChecked: + case ExpressionType.Not: + case ExpressionType.Convert: + case ExpressionType.ConvertChecked: + case ExpressionType.ArrayLength: + case ExpressionType.Quote: + case ExpressionType.TypeAs: + return VisitUnary((UnaryExpression)exp); + case ExpressionType.Add: + case ExpressionType.AddChecked: + case ExpressionType.Subtract: + case ExpressionType.SubtractChecked: + case ExpressionType.Multiply: + case ExpressionType.MultiplyChecked: + case ExpressionType.Divide: + case ExpressionType.Modulo: + case ExpressionType.And: + case ExpressionType.AndAlso: + case ExpressionType.Or: + case ExpressionType.OrElse: + case ExpressionType.LessThan: + case ExpressionType.LessThanOrEqual: + case ExpressionType.GreaterThan: + case ExpressionType.GreaterThanOrEqual: + case ExpressionType.Equal: + case ExpressionType.NotEqual: + case ExpressionType.Coalesce: + case ExpressionType.ArrayIndex: + case ExpressionType.RightShift: + case ExpressionType.LeftShift: + case ExpressionType.ExclusiveOr: + return VisitBinary((BinaryExpression)exp); + case ExpressionType.TypeIs: + return VisitTypeIs((TypeBinaryExpression)exp); + case ExpressionType.Conditional: + return VisitConditional((ConditionalExpression)exp); + case ExpressionType.Constant: + return VisitConstant((ConstantExpression)exp); + case ExpressionType.Parameter: + return VisitParameter((ParameterExpression)exp); + case ExpressionType.MemberAccess: + return VisitMemberAccess((MemberExpression)exp); + case ExpressionType.Call: + return VisitMethodCall((MethodCallExpression)exp); + case ExpressionType.Lambda: + return VisitLambda((LambdaExpression)exp); + case ExpressionType.New: + return VisitNew((NewExpression)exp); + case ExpressionType.NewArrayInit: + case ExpressionType.NewArrayBounds: + return VisitNewArray((NewArrayExpression)exp); + case ExpressionType.Invoke: + return VisitInvocation((InvocationExpression)exp); + case ExpressionType.MemberInit: + return VisitMemberInit((MemberInitExpression)exp); + case ExpressionType.ListInit: + return VisitListInit((ListInitExpression)exp); + default: + throw new NotSupportedException(String.Format("Unhandled expression type: '{0}'", exp.NodeType)); + } + } + + protected virtual MemberBinding VisitBinding(MemberBinding binding) + { + switch (binding.BindingType) + { + case MemberBindingType.Assignment: + return VisitMemberAssignment((MemberAssignment)binding); + case MemberBindingType.MemberBinding: + return VisitMemberMemberBinding((MemberMemberBinding)binding); + case MemberBindingType.ListBinding: + return VisitMemberListBinding((MemberListBinding)binding); + default: + throw new NotSupportedException(string.Format("Unhandled binding type '{0}'", binding.BindingType)); + } + } + + protected virtual ElementInit VisitElementInitializer(ElementInit initializer) + { + ReadOnlyCollection<Expression> arguments = VisitList(initializer.Arguments); + if (arguments != initializer.Arguments) + { + return Expression.ElementInit(initializer.AddMethod, arguments); + } + return initializer; + } + + protected virtual Expression VisitUnary(UnaryExpression u) + { + Expression operand = Visit(u.Operand); + if (operand != u.Operand) + { + return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method); + } + return u; + } + + protected virtual Expression VisitBinary(BinaryExpression b) + { + Expression left = Visit(b.Left); + Expression right = Visit(b.Right); + Expression conversion = Visit(b.Conversion); + + if (left != b.Left || right != b.Right || conversion != b.Conversion) + { + if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null) + return Expression.Coalesce(left, right, conversion as LambdaExpression); + else + return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method); + } + return b; + } + + protected virtual Expression VisitTypeIs(TypeBinaryExpression b) + { + Expression expr = Visit(b.Expression); + if (expr != b.Expression) + { + return Expression.TypeIs(expr, b.TypeOperand); + } + return b; + } + + protected virtual Expression VisitConstant(ConstantExpression c) + { + return c; + } + + protected virtual Expression VisitConditional(ConditionalExpression c) + { + Expression test = Visit(c.Test); + Expression ifTrue = Visit(c.IfTrue); + Expression ifFalse = Visit(c.IfFalse); + + if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse) + { + return Expression.Condition(test, ifTrue, ifFalse); + } + + return c; + } + + protected virtual Expression VisitParameter(ParameterExpression p) + { + return p; + } + + protected virtual Expression VisitMemberAccess(MemberExpression m) + { + Expression exp = Visit(m.Expression); + if (exp != m.Expression) + { + return Expression.MakeMemberAccess(exp, m.Member); + } + return m; + } + + protected virtual Expression VisitMethodCall(MethodCallExpression m) + { + Expression obj = Visit(m.Object); + IEnumerable<Expression> args = VisitList(m.Arguments); + + if (obj != m.Object || args != m.Arguments) + { + return Expression.Call(obj, m.Method, args); + } + + return m; + } + + protected virtual ReadOnlyCollection<Expression> VisitList(ReadOnlyCollection<Expression> original) + { + List<Expression> list = null; + for (int i = 0, n = original.Count; i < n; i++) + { + Expression p = Visit(original[i]); + if (list != null) + { + list.Add(p); + } + else if (p != original[i]) + { + list = new List<Expression>(n); + for (int j = 0; j < i; j++) + { + list.Add(original[j]); + } + list.Add(p); + } + } + + if (list != null) + return list.AsReadOnly(); + + return original; + } + + protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) + { + Expression e = Visit(assignment.Expression); + + if (e != assignment.Expression) + { + return Expression.Bind(assignment.Member, e); + } + + return assignment; + } + + protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) + { + IEnumerable<MemberBinding> bindings = VisitBindingList(binding.Bindings); + + if (bindings != binding.Bindings) + { + return Expression.MemberBind(binding.Member, bindings); + } + + return binding; + } + + protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) + { + IEnumerable<ElementInit> initializers = VisitElementInitializerList(binding.Initializers); + + if (initializers != binding.Initializers) + { + return Expression.ListBind(binding.Member, initializers); + } + return binding; + } + + protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original) + { + List<MemberBinding> list = null; + for (int i = 0, n = original.Count; i < n; i++) + { + MemberBinding b = VisitBinding(original[i]); + if (list != null) + { + list.Add(b); + } + else if (b != original[i]) + { + list = new List<MemberBinding>(n); + for (int j = 0; j < i; j++) + { + list.Add(original[j]); + } + list.Add(b); + } + } + + if (list != null) + return list; + + return original; + } + + protected virtual IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original) + { + List<ElementInit> list = null; + for (int i = 0, n = original.Count; i < n; i++) + { + ElementInit init = VisitElementInitializer(original[i]); + if (list != null) + { + list.Add(init); + } + else if (init != original[i]) + { + list = new List<ElementInit>(n); + for (int j = 0; j < i; j++) + { + list.Add(original[j]); + } + list.Add(init); + } + } + + if (list != null) + return list; + + return original; + } + + protected virtual Expression VisitLambda(LambdaExpression lambda) + { + Expression body = Visit(lambda.Body); + if (body != lambda.Body) + { + return Expression.Lambda(lambda.Type, body, lambda.Parameters); + } + return lambda; + } + + protected virtual N... [truncated message content] |
From: <jer...@us...> - 2009-01-02 23:58:21
|
Revision: 213 http://structuremap.svn.sourceforge.net/structuremap/?rev=213&view=rev Author: jeremydmiller Date: 2009-01-02 23:58:17 +0000 (Fri, 02 Jan 2009) Log Message: ----------- documentation Modified Paths: -------------- trunk/Source/HTML/AttributeNormalized.htm trunk/Source/HTML/ConfiguringStructureMap.htm trunk/Source/HTML/ConstructorAndSetterInjection.htm trunk/Source/HTML/Default.htm trunk/Source/HTML/Diagnostics.htm trunk/Source/HTML/ExtendingStructureMap.htm trunk/Source/HTML/Generics.htm trunk/Source/HTML/Glossary.htm trunk/Source/HTML/HTML.csproj trunk/Source/HTML/InstanceExpression.htm trunk/Source/HTML/Interception.htm trunk/Source/HTML/QuickStart.htm trunk/Source/HTML/RegistryDSL.htm trunk/Source/HTML/RetrievingServices.htm trunk/Source/HTML/ScanningAssemblies.htm Added Paths: ----------- trunk/Source/HTML/AutoMocker.htm trunk/Source/HTML/AutoWiring.htm trunk/Source/HTML/ChangingConfigurationAtRuntime.htm trunk/Source/HTML/Concepts.htm trunk/Source/HTML/FeatureList.htm trunk/Source/HTML/HowDoesStructureMapWork.htm trunk/Source/HTML/Menu.htm trunk/Source/HTML/ModularConfiguration.htm trunk/Source/HTML/Profiles.htm trunk/Source/HTML/Scoping.htm trunk/Source/HTML/SmartInstance.htm trunk/Source/HTML/UsingAttributes.htm trunk/Source/HTML/UsingSessionContext.htm trunk/Source/HTML/UsingTheContainerOutsideOfObjectFactory.htm trunk/Source/HTML/XmlReference.htm trunk/Source/HTML/jquery-1.2.6.js trunk/Source/HTML/structuremap.js trunk/Source/HTML/style.css Removed Paths: ------------- trunk/Source/HTML/ExplicitArguments.htm trunk/Source/HTML/InjectingServicesAtRuntime.htm Modified: trunk/Source/HTML/AttributeNormalized.htm =================================================================== --- trunk/Source/HTML/AttributeNormalized.htm 2008-12-22 14:57:59 UTC (rev 212) +++ trunk/Source/HTML/AttributeNormalized.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -1,25 +1,18 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> - <title>Title</title> - <link rel="stylesheet" type="text/css" href="style.css"> - <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"> - <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> - <style type="text/css"> - .style1 - { - font-weight: bold; - } - </style> + <title>Attribute Normalized Instances</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> - <h1>Attribute Normalized Xml Instances</h1> + <body class="code"> <p>This style is a more terse configuration format that was added in version 1.0. My recommendaton is to always use attribute normalized Xml configuration by marking the <StructureMap> node with the MementoStyle="Attribute" attribute by default anytime you are using Xml configuration. </p> - <h4>Instance Root Node</h4> + <h2>Instance Root Node</h2> <p>An Instance is defined in Xml starting from a root node. The actual name of the root node varies depending upon the context that an Instance is being configured. For example, the AddInstance, DefaultInstance, @@ -31,7 +24,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;\red163\green21\blue21;\red0\green0\blue255;}??\fs20 [\cf3 Pluggable\cf0 (\cf4 "Color"\cf0 )]\par ?? \cf5 public\cf0 \cf5 class\cf0 \cf3 ColorRule\cf0 : \cf3 Rule\par ??\cf0 \{\par ?? \cf5 private\cf0 \cf5 string\cf0 _Color;\par ?? \cf5 public\cf0 \cf5 string\cf0 ID = \cf3 Guid\cf0 .NewGuid().ToString();\par ??\par ?? \cf5 public\cf0 ColorRule(\cf5 string\cf0 Color)\par ?? \{\par ?? _Color = Color;\par ?? \}\par ??\par ??\par ?? \cf5 public\cf0 \cf5 string\cf0 Color\par ?? \{\par ?? \cf5 get\cf0 \{ \cf5 return\cf0 _Color; \}\par ?? \}\par ?? \}} --> - <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> + <div class="code-sample" + style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> <p style="margin: 0px;"> [<span style="color: #2b91af;">Pluggable</span>(<span style="color: #a31515;">"Color"</span>)]</p> @@ -82,7 +76,7 @@ {\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 Instance\cf1 \cf4 Key\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 \cf4 Type\cf1 =\cf0 "\cf1 Color\cf0 "\cf1 \cf4 Color\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 />} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> - <p style="margin: 0px;"> + <p style="margin: 0px;" class="code-sample"> <span style="color: blue;"> <</span><span style="color: #a31515;">Instance</span><span style="color: blue;"> </span> <span style="color: red;">Key</span><span style="color: blue;">=</span>"<span @@ -102,7 +96,7 @@ {\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 Instance\cf1 \cf4 Key\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Widget.Color, StructureMap.Testing.Widget\cf0 "\cf1 \cf4 Color\cf1 =\cf0 "\cf1 Red\cf0 "\cf1 />} --> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white;"> - <p style="margin: 0px;"> + <p style="margin: 0px;" class="code-sample"> <span style="color: blue;"> <</span><span style="color: #a31515;">Instance</span><span style="color: blue;"> </span> <span style="color: red;">Key</span><span style="color: blue;">=</span>"<span @@ -114,26 +108,30 @@ style="color: blue;">Red</span>"<span style="color: blue;"> /></span></p> </div> <!--EndFragment--> -<p> </p> - <h4>Primitive Properties (Strings and basic value types)</h4> - <p>Primitive constructor or setter arguments are defined by - adding an attribute @propertyName="propertyValue" to the - instance node.="font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt;"> -<pre style="margin: 0px;"> [Pluggable("Color", "Only for testing")]</pre> -<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> ColorWidget : IWidget</pre> +<hr /> + <h2>Primitive Properties (Strings and basic value types)</h2> + <p>Primitive constructor or setter arguments are defined by adding an attribute + @propertyName="propertyValue" to the instance node. A class with + a string argument to the constructor,</p> +<div class="code-sample> + <pre style="margin: 0px;"> [Pluggable("Color", "Only for testing")]<pre style="margin: 0px;"> <span style="color: blue;">public</span> <span style="color: blue;">class</span> ColorWidget : IWidget</pre> <pre style="margin: 0px;"> {</pre> <pre style="margin: 0px;"> <span style="color: blue;">public</span> ColorWidget(<span style="color: blue;">string</span> Color)</pre> <pre style="margin: 0px;"> {</pre> <pre style="margin: 0px;"> _Color = Color;</pre> <pre style="margin: 0px;"> }</pre> <pre style="margin: 0px;"> }</pre> + <pre style="margin: 0px;"> </pre> + <p style="margin: 0px;">would be configured like this in the Xml:</p> + </div> <br> <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt;"> -<pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">Widget</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Color"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Red"</span><span style="color: fuchsia;"> </span><span style="color: #FF0000">Color</span><span style="color: blue;">="Red" /></span></pre> +<pre style="margin: 0px;" class="code-sample"> <span style="color: blue;"><</span><span style="color: maroon;">Widget</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Color"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Red"</span><span style="color: fuchsia;"> </span><span style="color: #FF0000">Color</span><span style="color: blue;">="Red" /></span></pre> </div> -<h4>Long Strings</h4> + <hr /> + <h2>Long Strings</h2> <p>There is an optional mode to define a property value inside a CDATA tag for very long strings like sql statements or Javascript templates. </p> @@ -150,7 +148,8 @@ <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">Property</span><span style="color: blue;">></span></pre> </div> - <h4>Enumeration Properties</h4> + <hr /> + <h2>Enumeration Properties</h2> <p>Enumeration arguments are defined the same way as primitive properties. Use the string names of the enumeration for the values.</p> @@ -181,7 +180,8 @@ <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border-top: windowtext 1pt solid; padding-top: 0pt; border-left: windowtext 1pt solid; padding-left: 0pt; border-right: windowtext 1pt solid; padding-right: 0pt; border-bottom: windowtext 1pt solid; padding-bottom: 0pt;"> <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: #800000">Instance</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Cow"</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Maggie" </span><span style="color: #FF0000">Breed</span><span style="color: blue;">="Angus" /></span></pre> </div> - <h4>Child Properties</h4> + <hr /> + <h2>Child Properties</h2> <p>Child properties of non-primitive types are defined as embedded memento nodes. Child properties can be either defined inline or use a reference to a named instance of the @@ -229,7 +229,8 @@ <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: maroon;">MyGrandChild</span><span style="color: fuchsia;"> </span><span style="color: red;">Key</span><span style="color: blue;">="Tommy"/></span></pre> <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">StructureMap.Testing.Widget.Child</span><span style="color: blue;">></span> </pre> </div> -<h3>Non Primitive Array Property</h3> + <hr /> + <h2>Non Primitive Array Property</h2> <p>If a property or constructor argument is an array of a non-primitive type, create a child node to the top level instance node with the name of the property. Simply add new InstanceMemento nodes with the name <Child> under the property @@ -258,8 +259,10 @@ <pre style="margin: 0px;"> <span style="color: blue;"><</span><span style="color: #800000">Child</span><span style="color: fuchsia;"> </span><span style="color: red;">Type</span><span style="color: blue;">="Random" </span><span style="color: #FF0000">seed</span><span style="color: blue;">="0.034"/></span></pre> <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">innerStrategies</span><span style="color: blue;">></span></pre> <pre style="margin: 0px;"> <span style="color: blue;"></</span><span style="color: maroon;">Instance</span><span style="color: blue;">></span></pre> + <p style="margin: 0px;"> </p> + <hr /> </div> -<h3>Primitive Arrays</h3> +<h2>Primitive Arrays</h2> <p>Primitive arrays like string[] or int[] can be defined in Xml. For a class with arguments like:</p> <!-- @@ -284,7 +287,8 @@ <!-- {\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 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\cf1 >\par ??\par ?? <\cf3 numbers\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1,2,3\cf0 "\cf1 />\par ?? <\cf3 strings\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1,2,3\cf0 "\cf1 />\par ?? </\cf3 DefaultInstance\cf1 >} --> - <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;"> <</span><span style="color: #a31515;">DefaultInstance</span></p> <p style="margin: 0px;"> @@ -321,7 +325,8 @@ <!-- {\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 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithStringAndIntArray, StructureMap.Testing\cf0 "\cf1 >\par ??\par ?? <\cf3 numbers\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1;2;3\cf0 "\cf1 \cf4 Delimiter\cf1 =\cf0 "\cf1 ;\cf0 "\cf1 />\par ?? <\cf3 strings\cf1 \cf4 Values\cf1 =\cf0 "\cf1 1,2,3\cf0 "\cf1 />\par ?? </\cf3 DefaultInstance\cf1 >} --> -<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;"> <</span><span style="color: #a31515;">DefaultInstance</span></p> <p style="margin: 0px;"> @@ -352,14 +357,16 @@ style="color: blue;">></span></p> </div> <!--EndFragment--> -<h3>Dictionaries and NameValueCollection</h3> +<hr /> + <h2>Dictionaries and NameValueCollection</h2> <p>Any form of IDictionary<Key, Value> or a NameValueCollection can be configured in Xml by the following syntax. Say you have a class that needs a Dictionary of properties:</p> <!-- {\rtf1\ansi\ansicpg\lang1024\noproof65001\uc1 \deff0{\fonttbl{\f0\fnil\fcharset0\fprq1 Courier New;}}{\colortbl;??\red0\green0\blue0;\red255\green255\blue255;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 public\cf0 \cf3 class\cf0 \cf4 ClassWithDictionary\par ??\cf0 \{\par ?? \cf3 private\cf0 \cf3 readonly\cf0 \cf4 IDictionary\cf0 <\cf3 string\cf0 , \cf3 string\cf0 > _dictionary;\par ??\par ?? \cf3 public\cf0 ClassWithDictionary(\cf4 IDictionary\cf0 <\cf3 string\cf0 , \cf3 string\cf0 > dictionary)\par ?? \{\par ?? _dictionary = dictionary;\par ?? \}\par ??\par ?? \cf3 public\cf0 \cf4 IDictionary\cf0 <\cf3 string\cf0 , \cf3 string\cf0 > Dictionary\par ?? \{\par ?? \cf3 get\cf0 \{ \cf3 return\cf0 _dictionary; \}\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: blue;">public</span> <span style="color: blue;"> class</span> <span style="color: #2b91af;">ClassWithDictionary</span></p> @@ -410,7 +417,8 @@ <!-- {\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 DefaultInstance\par ??\cf1 \cf4 PluginType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithDictionary, StructureMap.Testing\cf0 "\par ??\cf1 \cf4 PluggedType\cf1 =\cf0 "\cf1 StructureMap.Testing.Configuration.ClassWithDictionary, StructureMap.Testing\cf0 "\cf1 >\par ?? <\cf3 dictionary\cf1 >\par ?? <\cf3 Pair\cf1 \cf4 Key\cf1 =\cf0 '\cf1 color\cf0 '\cf1 \cf4 Value\cf1 =\cf0 '\cf1 red\cf0 '\cf1 />\par ?? <\cf3 Pair\cf1 \cf4 Key\cf1 =\cf0 '\cf1 state\cf0 '\cf1 \cf4 Value\cf1 =\cf0 '\cf1 texas\cf0 '\cf1 />\par ?? <\cf3 Pair\cf1 \cf4 Key\cf1 =\cf0 '\cf1 direction\cf0 '\cf1 \cf4 Value\cf1 =\cf0 '\cf1 north\cf0 '\cf1 />\par ?? </\cf3 dictionary\cf1 >\par ?? </\cf3 DefaultInstance\cf1 >} --> - <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;"> <</span><span style="color: #a31515;">DefaultInstance</span></p> <p style="margin: 0px;"> @@ -456,7 +464,7 @@ <p>Just create a new node for the IDictionary property called <[propertyName]> under the main instance node. Then add a <Pair Key="key" Value="value"/> node for each name/value pair in the IDictionary. </p> -<p> </p> + <hr /> </body> </html> Added: trunk/Source/HTML/AutoMocker.htm =================================================================== --- trunk/Source/HTML/AutoMocker.htm (rev 0) +++ trunk/Source/HTML/AutoMocker.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -0,0 +1,9 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title></title> + </head> + <body> + + </body> +</html> \ No newline at end of file Added: trunk/Source/HTML/AutoWiring.htm =================================================================== --- trunk/Source/HTML/AutoWiring.htm (rev 0) +++ trunk/Source/HTML/AutoWiring.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -0,0 +1,461 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Auto Wiring</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> + The best way to use an IoC container is to allow "Auto Wiring" to do most of the + work for you. IoC Containers like StructureMap are an infrastructure + concern, and as such, should be isolated from as much of your code as possible. + Before examining Auto Wiring in depth, let's look at a common anti pattern of + IoC usage:</p> + <h2> + IoC Container Anti-Pattern</h2> + <p> + One of the worst, but sadly most common, usages of an IoC container 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\green128\blue0;\red0\green0\blue255;\red43\green145\blue175;}??\fs20 \cf3 // This is the way to write a Constructor Function with an IoC tool\par ??\cf0 \cf3 // Let the IoC container "inject" services from outside, and keep\par ??\cf0 \cf3 // ShippingScreenPresenter ignorant of the IoC infrastructure\par ??\cf0 \cf4 public\cf0 ShippingScreenPresenter(\cf5 IShippingService\cf0 service, \cf5 IRepository\cf0 repository)\par ?? \{\par ?? _service = service;\par ?? _repository = repository;\par ?? \}\par ??\par ?? \cf3 // FAIL!\par ??\cf0 \cf3 // This is the wrong way to use an IoC container. Do NOT invoke the container from\par ??\cf0 \cf3 // the constructor function. This tightly couples the ShippingScreenPresenter to\par ??\cf0 \cf3 // the IoC container in a harmful way. This class cannot be used in either\par ??\cf0 \cf3 // production or testing without a valid IoC configuration. Plus, you're writing more\par ??\cf0 \cf3 // code\par ??\cf0 \cf4 public\cf0 ShippingScreenPresenter()\par ?? \{\par ?? _service = \cf5 ObjectFactory\cf0 .GetInstance<\cf5 IShippingService\cf0 >();\par ?? _repository = \cf5 ObjectFactory\cf0 .GetInstance<\cf5 IRepository\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: green;">// This is the way to + write a Constructor Function with an IoC tool</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// Let the IoC container + "inject" services from outside, and keep</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// + ShippingScreenPresenter ignorant of the IoC infrastructure</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ShippingScreenPresenter(<span style="color: #2b91af;">IShippingService</span> + service, <span style="color: #2b91af;">IRepository</span> repository)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _service = service;</p> + <p style="margin: 0px;"> + _repository = repository;</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: green;">// FAIL!</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// This is the wrong way + to use an IoC container. Do NOT invoke the container from</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// the constructor + function. This tightly couples the ShippingScreenPresenter to</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// the IoC container in a + harmful way. This class cannot be used in either</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// production or testing + without a valid IoC configuration. Plus, you're writing more</span></p> + <p style="margin: 0px;"> + <span style="color: green;">// code</span></p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ShippingScreenPresenter()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _service = + <span style="color: #2b91af;">ObjectFactory</span>.GetInstance<<span + style="color: #2b91af;">IShippingService</span>>();</p> + <p style="margin: 0px;"> + _repository = + <span style="color: #2b91af;">ObjectFactory</span>.GetInstance<<span + style="color: #2b91af;">IRepository</span>>();</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<hr /> + <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"> + <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> + <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"> + IRepository</span> _repository;</p> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">private</span> + <span style="COLOR: blue">readonly</span> <span style="COLOR: #2b91af"> + IValidator</span> _validator;</p> + <p style="MARGIN: 0px"> + </p> + <p style="MARGIN: 0px"> + <span style="COLOR: green">// SomeScreenController + depends on both IRepository and IValidator</span></p> + <p style="MARGIN: 0px"> + <span style="COLOR: blue">public</span> + SomeScreenController(<span style="COLOR: #2b91af">IRepository</span> repository, + <span style="COLOR: #2b91af">IValidator</span> validator)</p> + <p style="MARGIN: 0px"> + {</p> + <p style="MARGIN: 0px"> + _repository = repository;</p> + <p style="MARGIN: 0px"> + _validator = validator;</p> + <p style="MARGIN: 0px"> + }</p> + <p style="MARGIN: 0px"> + </p> + <p style="MARGIN: 0px"> + }</p> + </div> + <p> + So let’s get StructureMap set up for this SomeScreenController class:</p> + <div style="BORDER-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"> + <span style="COLOR: #2b91af"> + ObjectFactory</span>.Initialize(x =></p> + <p style="MARGIN: 0px"> + {</p> + <p style="MARGIN: 0px"> + + <span style="COLOR: green">// Set up the IValidator</span></p> + <p style="MARGIN: 0px"> + + x.ForRequestedType<<span style="COLOR: #2b91af">IValidator</span>>().TheDefaultIsConcreteType<<span + style="COLOR: #2b91af">Validator</span>>();</p> + <p style="MARGIN: 0px"> + </p> + <p style="MARGIN: 0px"> + + <span style="COLOR: green">// Set up the IRepository</span></p> + <p style="MARGIN: 0px"> + + x.ForRequestedType<<span style="COLOR: #2b91af">IRepository</span>>().TheDefault.Is.OfConcreteType<<span + style="COLOR: #2b91af">Repository</span>>()</p> + <p style="MARGIN: 0px"> + + .WithCtorArg(<span style="COLOR: #a31515">"connectionString"</span>).EqualToAppSetting(<span + style="COLOR: #a31515">"CONNECTION-STRING"</span>);</p> + <p style="MARGIN: 0px"> + });</p> + </div> + <p> + You’ll notice that we didn’t make any explicit configuration for the + SomeScreenController class, but yet we could now call:</p> + <div style="BORDER-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"> + <span style="COLOR: blue">var</span> + controller = <span style="COLOR: #2b91af">ObjectFactory</span>.GetInstance<<span + style="COLOR: #2b91af">SomeScreenController</span>>();</p> + </div> + <p> + and StructureMap will happily create a new instance of the SomeScreenController + class by invoking its constructor and passing in a new Validator object and a + new Repository object created with the connection string from the App.config + file. We didn’t need to tell StructureMap how to construct + SomeScreenController because: + </p> + <ul> + <li>StructureMap can look at the constructor function of SomeScreenController and + see that it depends on IValidator and IRepository </li> + <li>StructureMap “knows” about the default way to create and return an IValidator + and an IRepository </li> + </ul> + <p> + This feature is known as “auto wiring,” and all the mainstream IoC containers + support this feature to some extent or another. + </p> + <hr /> + <h2>StructureMap's Policies for Auto Wiring</h2> + <p>By default, as long as an object is being created by invoking its constructor + function, StructureMap will try to create/resolve/find an object for each + non-primitive dependency in the requested concrete type. If StructureMap + doesn't "know" how to find a requested dependency, it will throw an exception. + By design, StructureMap cannot auto wire primitive arguments like strings and + numbers. The Auto Wiring can be overriden by explicit configuration (this + might actually be easier with Xml 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;\red163\green21\blue21;}??\fs20 registry.InstanceOf<\cf3 Rule\cf0 >()\par ?? .Is.OfConcreteType<\cf3 WidgetRule\cf0 >()\par ?? .WithName(\cf4 "TheWidgetRule"\cf0 )\par ?? .CtorDependency<\cf3 IWidget\cf0 >().Is(i => i.TheInstanceNamed(\cf4 "Yellow"\cf0 ));} +--> + <div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid;"> + <p style="margin: 0px;"> + + registry.InstanceOf<<span style="color: #2b91af;">Rule</span>>()</p> + <p style="margin: 0px;"> + + .Is.OfConcreteType<<span style="color: #2b91af;">WidgetRule</span>>()</p> + <p style="margin: 0px;"> + + .WithName(<span style="color: #a31515;">"TheWidgetRule"</span>)</p> + <p style="margin: 0px;"> + + .CtorDependency<<span style="color: #2b91af;">IWidget</span>>().Is(i => + i.TheInstanceNamed(<span style="color: #a31515;">"Yellow"</span>));</p> + </div> +<!--EndFragment--> +<p>In the example above, the IWidget dependency of the WidgetRule class is + overriden.</p> + <hr /> + <h4>Object Identity within a Single Request</h4> + <p>TODO</p> + <hr /> + <h4>Injecting Arrays of Services</h4> + <p>TODO</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 ?? \}} +--> + <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;">IValidator</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;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">Validator</span> : <span style="color: #2b91af;"> + IValidator</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: blue;">string</span> + _name;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> Validator(<span + style="color: blue;">string</span> name)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _name = name;</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;">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;">"Name: {0}"</span>, _name);</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> <span style="color: blue;">class</span> + <span style="color: #2b91af;">ClassThatUsesValidators</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;"> + IValidator</span>[] _validators;</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + <span style="color: blue;">public</span> + ClassThatUsesValidators(<span style="color: #2b91af;">IValidator</span>[] + validators)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + _validators = validators;</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;">void</span> Write()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;"> + foreach</span> (<span style="color: #2b91af;">IValidator</span> validator + <span style="color: blue;">in</span> _validators)</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: #2b91af;">Debug</span>.WriteLine(validator);</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;"> + [<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;">ValidatorExamples</span></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: blue;">private</span> + <span style="color: #2b91af;">Container</span> container;</p> + <p style="margin: 0px;"> + </p> + <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;"> + + x.ForRequestedType<<span style="color: #2b91af;">IValidator</span>>().AddInstances(o + =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Red"</span>).WithName(<span + style="color: #a31515;">"Red"</span>);</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Blue"</span>).WithName(<span + style="color: #a31515;">"Blue"</span>);</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Purple"</span>).WithName(<span + style="color: #a31515;">"Purple"</span>);</p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">Validator</span>>().WithCtorArg(<span + style="color: #a31515;">"name"</span>).EqualTo(<span + style="color: #a31515;">"Green"</span>).WithName(<span + style="color: #a31515;">"Green"</span>);</p> + <p style="margin: 0px;"> + });</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + x.ForRequestedType<<span style="color: #2b91af;">ClassThatUsesValidators</span>>().AddInstances(o + =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + + <span style="color: green;">// Define an Instance of ClassThatUsesValidators + that depends on AutoWiring</span></p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">ClassThatUsesValidators</span>>().WithName(<span + style="color: #a31515;">"WithAutoWiring"</span>);</p> + <p style="margin: 0px;"> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// Define an Instance of ClassThatUsesValidators + that overrides AutoWiring</span></p> + <p style="margin: 0px;"> + + o.OfConcreteType<<span style="color: #2b91af;">ClassThatUsesValidators</span>>().WithName(<span + style="color: #a31515;">"ExplicitArray"</span>)</p> + <p style="margin: 0px;"> + + .TheArrayOf<<span style="color: #2b91af;">IValidator</span>>().Contains(y =></p> + <p style="margin: 0px;"> + + {</p> + <p style="margin: 0px;"> + + y.TheInstanceNamed(<span style="color: #a31515;">"Red"</span>);</p> + <p style="margin: 0px;"> + + y.TheInstanceNamed(<span style="color: #a31515;">"Green"</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> + <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> what_are_the_validators()</p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"With Auto Wiring"</span>);</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">ClassThatUsesValidators</span>>(<span + style="color: #a31515;">"WithAutoWiring"</span>).Write();</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"================================="</span>);</p> + <p style="margin: 0px;"> + <span style="color: #2b91af;"> + Debug</span>.WriteLine(<span style="color: #a31515;">"With Explicit + Configuration"</span>);</p> + <p style="margin: 0px;"> + container.GetInstance<<span + style="color: #2b91af;">ClassThatUsesValidators</span>>(<span + style="color: #a31515;">"ExplicitArray"</span>).Write();</p> + <p style="margin: 0px;"> + }</p> + <p style="margin: 0px;"> + }</p> + </div> +<!--EndFragment--> +<p> </p> + <p> </p> + <hr /> + </body> +</html> \ No newline at end of file Copied: trunk/Source/HTML/ChangingConfigurationAtRuntime.htm (from rev 204, trunk/Source/HTML/InjectingServicesAtRuntime.htm) =================================================================== --- trunk/Source/HTML/ChangingConfigurationAtRuntime.htm (rev 0) +++ trunk/Source/HTML/ChangingConfigurationAtRuntime.htm 2009-01-02 23:58:17 UTC (rev 213) @@ -0,0 +1,405 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>Changing Configuration at Runtime</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>In the beginning (late 2003), there was attributes and there was a copious amount of Xml configuration, and I called it good. + Look Ma! I can radically change the behavior of the code without + recompiling, isn't that a marvelous thing? + Then we started to use StructureMap on a real project and quickly realized that + it would be very useful if we could override some services with mock objects in + our unit tests. In later projects I've run into scenarios where it would + be valuable to put an object into StructureMap after it was created. Other + users have asked for the ability to load assemblies or modules of their system + on demand so as to save memory. A major goal of the StructureMap 2.5 + release has been to greatly extend its capabilities for service registration at + runtime. With a very few exceptions, you can now make any and all + configuration changes after the first call to ObjectFactory. My + recommendation is to use this behavior simply and with caution because it will + bypass many of the diagnostic abilities built into StructureMap (i.e. + StructureMapDoctor might miss configuration problems introduced outside of the + normal configuration).</p> +<h2> + Adding Configuration to an Existing Container</h2> +<p> + In contrast to Initialize(), the Configure() method allows you to add additional + configuration to an existing Container or ObjectFactory. Think of this + scenario. You're building a composite application that contains multiple + modules spread over several assemblies, but you might not want to load any of + the configuration or types for a particular module until it's requested by the + user. In that case, you can use the Configure() method 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\green128\blue0;\red43\green145\blue175;\red163\green21\blue21;}??\fs20 \cf3 // This code would add any configuration from\par ??\cf0 \cf3 // Registry classes found in the \par ??\cf0 \cf3 // assembly named 'MyApplication.Module1'\par ??\cf0 \cf4 ObjectFactory\cf0 .Configure(x =>\par ?? \{\par ?? x.Scan(scan =>\par ?? \{\par ?? scan.LookForRegistries();\par ?? scan.Assembly(\cf5 "MyApplication.Module1"\cf0 );\par ?? \});\par ?? \});} +--> +<div style="font-family: Courier New; font-size: 10pt; color: black; background: white; border: black thin solid; overflow: scroll;"> + <p style="margin: 0px;"> + + <span style="color: green;">// This code would add any configuration from</span></p> + <p style="margin: 0px;"> + + <span style="color: green;">// Registry classes found in the </span> + </p> + <p style="margin: 0px;"> + + <span style="color: green;">// assembly named 'MyApplication.Module1'</span></p> + <p style="margin: 0px;"> + + <span style="color: #2b91af;">ObjectFactory</span>.Configure(x =></p> + <p style="margin: 0px;"> + {</p> + <p style="margin: 0px;"> + ... [truncated message content] |
From: <jer...@us...> - 2008-12-22 14:58:19
|
Revision: 212 http://structuremap.svn.sourceforge.net/structuremap/?rev=212&view=rev Author: jeremydmiller Date: 2008-12-22 14:57:59 +0000 (Mon, 22 Dec 2008) Log Message: ----------- Fixed a minor problem with explicit arguments and concrete classes Modified Paths: -------------- trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/Extensions.cs trunk/Source/StructureMap/Graph/AssemblyScanner.cs trunk/Source/StructureMap/Graph/TypeRules.cs trunk/Source/StructureMap/Pipeline/Instance.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs Added Paths: ----------- trunk/Source/StructureMap/TypeExtensions.cs Modified: trunk/Source/StructureMap/Container.cs =================================================================== --- trunk/Source/StructureMap/Container.cs 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap/Container.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -109,6 +109,11 @@ { Instance defaultInstance = _pipelineGraph.GetDefault(pluginType); + if (defaultInstance == null && pluginType.IsConcrete()) + { + defaultInstance = new ConfiguredInstance(pluginType); + } + BasicInstance basicInstance = defaultInstance as BasicInstance; Instance instance = basicInstance == null ? defaultInstance : new ExplicitInstance(pluginType, args, basicInstance); Modified: trunk/Source/StructureMap/Extensions.cs =================================================================== --- trunk/Source/StructureMap/Extensions.cs 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap/Extensions.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -5,7 +5,7 @@ namespace StructureMap { - public static class StringExtensions + internal static class StringExtensions { public static string ToFormat(this string template, params object[] parameters) { Modified: trunk/Source/StructureMap/Graph/AssemblyScanner.cs =================================================================== --- trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap/Graph/AssemblyScanner.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -7,14 +7,6 @@ namespace StructureMap.Graph { - public static class TypeExtensions - { - public static bool IsInNamespace(this Type type, string nameSpace) - { - return type.Namespace.StartsWith(nameSpace); - } - } - public interface IAssemblyScanner { #region Designating Assemblies Modified: trunk/Source/StructureMap/Graph/TypeRules.cs =================================================================== --- trunk/Source/StructureMap/Graph/TypeRules.cs 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap/Graph/TypeRules.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -76,7 +76,7 @@ return type.IsPrimitive && !IsString(type) && type != typeof (IntPtr); } - protected bool IsSimple(Type type) + protected internal bool IsSimple(Type type) { return type.IsPrimitive || IsString(type) || IsEnum(type); } @@ -101,7 +101,7 @@ return type.IsArray && IsSimple(type.GetElementType()); } - protected bool IsConcrete(Type type) + protected internal bool IsConcrete(Type type) { return !type.IsInterface && !type.IsAbstract; } @@ -112,4 +112,6 @@ return IsChild(type) || IsChildArray(type); } } + + } \ No newline at end of file Modified: trunk/Source/StructureMap/Pipeline/Instance.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/Instance.cs 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap/Pipeline/Instance.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -5,14 +5,6 @@ namespace StructureMap.Pipeline { - public static class TypeExtensions - { - public static ReferencedInstance GetReferenceTo(this Type type) - { - string key = PluginCache.GetPlugin(type).ConcreteKey; - return new ReferencedInstance(key); - } - } public interface IInstance { Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap/StructureMap.csproj 2008-12-22 14:57:59 UTC (rev 212) @@ -406,6 +406,7 @@ <Compile Include="Graph\ITypeScanner.cs" /> <Compile Include="Graph\PluggableAttributeScanner.cs" /> <Compile Include="Graph\PluginCache.cs" /> + <Compile Include="TypeExtensions.cs" /> <Compile Include="IBootstrapper.cs" /> <Compile Include="InitializationExpression.cs" /> <Compile Include="Model.cs" /> Added: trunk/Source/StructureMap/TypeExtensions.cs =================================================================== --- trunk/Source/StructureMap/TypeExtensions.cs (rev 0) +++ trunk/Source/StructureMap/TypeExtensions.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -0,0 +1,25 @@ +using System; +using StructureMap.Graph; +using StructureMap.Pipeline; + +namespace StructureMap +{ + public static class TypeExtensions + { + public static bool IsInNamespace(this Type type, string nameSpace) + { + return type.Namespace.StartsWith(nameSpace); + } + + public static ReferencedInstance GetReferenceTo(this Type type) + { + string key = PluginCache.GetPlugin(type).ConcreteKey; + return new ReferencedInstance(key); + } + + public static bool IsConcrete(this Type type) + { + return new TypeRules().IsConcrete(type); + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs 2008-12-21 16:31:48 UTC (rev 211) +++ trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs 2008-12-22 14:57:59 UTC (rev 212) @@ -16,7 +16,10 @@ [SetUp] public void SetUp() { - ObjectFactory.Initialize(x => { x.UseDefaultStructureMapConfigFile = false; }); + ObjectFactory.Initialize(x => + { + x.UseDefaultStructureMapConfigFile = false; + }); } #endregion @@ -381,6 +384,14 @@ args.SetArg("age", 34); Assert.AreEqual(34, args.GetArg("age")); } + + [Test] + public void can_build_a_concrete_class_with_constructor_args_that_is_not_previously_registered() + { + var container = new Container(); + container.With("name").EqualTo("Jeremy").GetInstance<ConcreteThatNeedsString>() + .Name.ShouldEqual("Jeremy"); + } } public class Lump @@ -485,4 +496,19 @@ get { return _trade; } } } + + public class ConcreteThatNeedsString + { + private string _name; + + public ConcreteThatNeedsString(string name) + { + _name = name; + } + + public string Name + { + get { return _name; } + } + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-21 16:31:52
|
Revision: 211 http://structuremap.svn.sourceforge.net/structuremap/?rev=211&view=rev Author: jeremydmiller Date: 2008-12-21 16:31:48 +0000 (Sun, 21 Dec 2008) Log Message: ----------- A performance enhancement to stop SM from needing to scan the StructureMap dll on startup Modified Paths: -------------- trunk/Source/CommonAssemblyInfo.cs trunk/Source/StructureMap/Configuration/GraphBuilder.cs trunk/Source/StructureMap/Configuration/IGraphBuilder.cs trunk/Source/StructureMap/MementoSource.cs trunk/Source/StructureMap/Pipeline/IBuildInterceptor.cs trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs trunk/Source/StructureMap/PluginGraphBuilder.cs trunk/Source/StructureMap/Source/DirectoryXmlMementoSource.cs trunk/Source/StructureMap/Source/EmbeddedFolderXmlMementoSource.cs trunk/Source/StructureMap/Source/MemoryMementoSource.cs trunk/Source/StructureMap/Source/SingleEmbeddedXmlMementoSource.cs trunk/Source/StructureMap/Source/TemplatedMementoSource.cs trunk/Source/StructureMap/Source/XmlAttributeFileMementoSource.cs trunk/Source/StructureMap/Source/XmlFileMementoSource.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap.Testing/Configuration/NormalGraphBuilderTester.cs trunk/Source/StructureMap.sln Added Paths: ----------- trunk/Source/StructureMap/SystemRegistry.cs Modified: trunk/Source/CommonAssemblyInfo.cs =================================================================== --- trunk/Source/CommonAssemblyInfo.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/CommonAssemblyInfo.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -13,11 +13,11 @@ //------------------------------------------------------------------------------ [assembly: ComVisibleAttribute(false)] -[assembly: AssemblyVersionAttribute("2.5.0.0000")] +[assembly: AssemblyVersionAttribute("2.5.1.0000")] [assembly: AssemblyCopyrightAttribute("Copyright (c) 2003-2008, Jeremy D. Miller")] [assembly: AssemblyProductAttribute("StructureMap")] [assembly: AssemblyCompanyAttribute("")] [assembly: AssemblyConfigurationAttribute("release")] -[assembly: AssemblyInformationalVersionAttribute("2.5.0.0000")] -[assembly: AssemblyFileVersionAttribute("2.5.0.0000")] +[assembly: AssemblyInformationalVersionAttribute("2.5.1.0000")] +[assembly: AssemblyFileVersionAttribute("2.5.1.0000")] Modified: trunk/Source/StructureMap/Configuration/GraphBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/GraphBuilder.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Configuration/GraphBuilder.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.Reflection; using StructureMap.Configuration.DSL; using StructureMap.Graph; @@ -10,10 +11,9 @@ { private readonly AssemblyScanner _assemblyScanner; private readonly PluginGraph _pluginGraph; - private readonly PluginGraph _systemGraph; - private readonly AssemblyScanner _systemScanner; private Profile _profile; private Container _systemContainer; + private readonly PluginGraph _systemGraph; public GraphBuilder(Registry[] registries) : this(registries, new PluginGraph()) @@ -31,10 +31,8 @@ registry.ConfigurePluginGraph(_pluginGraph); } - _systemScanner = new AssemblyScanner(); - _systemScanner.Assembly(Assembly.GetExecutingAssembly()); - - _systemGraph = new PluginGraph(_systemScanner); + _systemGraph = new SystemRegistry().Build(); + _systemContainer = new Container(_systemGraph); } #region IGraphBuilder Members @@ -44,11 +42,6 @@ _pluginGraph.Seal(); } - public PluginGraph SystemGraph - { - get { return _systemGraph; } - } - public PluginGraph PluginGraph { get { return _pluginGraph; } @@ -60,7 +53,6 @@ { Assembly assembly = AppDomain.CurrentDomain.Load(assemblyName); _assemblyScanner.Assembly(assembly); - _systemScanner.Assembly(assembly); } catch (Exception ex) { @@ -68,11 +60,6 @@ } } - public void PrepareSystemObjects() - { - _systemGraph.Seal(); - } - public IProfileBuilder GetProfileBuilder() { return new ProfileBuilder(_pluginGraph); @@ -116,12 +103,6 @@ private object buildSystemObject(Type type, InstanceMemento memento) { Instance instance = memento.ReadInstance(_systemGraph, type); - - if (_systemContainer == null) - { - _systemContainer = new Container(_systemGraph); - } - return _systemContainer.GetInstance(type, instance); } } Modified: trunk/Source/StructureMap/Configuration/IGraphBuilder.cs =================================================================== --- trunk/Source/StructureMap/Configuration/IGraphBuilder.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Configuration/IGraphBuilder.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -15,11 +15,9 @@ public interface IGraphBuilder { - PluginGraph SystemGraph { get; } PluginGraph PluginGraph { get; } void AddAssembly(string assemblyName); - void PrepareSystemObjects(); void FinishFamilies(); IProfileBuilder GetProfileBuilder(); Modified: trunk/Source/StructureMap/MementoSource.cs =================================================================== --- trunk/Source/StructureMap/MementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/MementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -10,7 +10,6 @@ /// Abstract class that is the supertype of all storage and retrieval mechanisms of /// InstanceMemento instances /// </summary> - [PluginFamily] public abstract class MementoSource { private readonly Dictionary<string, InstanceMemento> _externalMementos = Modified: trunk/Source/StructureMap/Pipeline/IBuildInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/IBuildInterceptor.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Pipeline/IBuildInterceptor.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -3,7 +3,6 @@ /// <summary> /// Plugin interface to create custom build or lifecycle policies for a Plugin Type /// </summary> - [PluginFamily] public interface IBuildInterceptor : IBuildPolicy { IBuildPolicy InnerPolicy { get; set; } Modified: trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -2,7 +2,6 @@ namespace StructureMap.Pipeline { - [Pluggable("Singleton")] public class SingletonPolicy : CacheInterceptor { private readonly object _locker = new object(); Modified: trunk/Source/StructureMap/PluginGraphBuilder.cs =================================================================== --- trunk/Source/StructureMap/PluginGraphBuilder.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/PluginGraphBuilder.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -64,8 +64,6 @@ p.ParseAssemblies(graphBuilder); }); - graphBuilder.PrepareSystemObjects(); - forAllParsers(p => p.Parse(graphBuilder)); _graph.Seal(); Modified: trunk/Source/StructureMap/Source/DirectoryXmlMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/DirectoryXmlMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/DirectoryXmlMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -11,7 +11,6 @@ /// DirectoryXmlMementoSource is meant to simplify complicated object graph configurations by isolating each instance to a separate /// editable file. /// </summary> - [Pluggable("DirectoryXml")] public class DirectoryXmlMementoSource : MementoSource { private readonly string _directory; Modified: trunk/Source/StructureMap/Source/EmbeddedFolderXmlMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/EmbeddedFolderXmlMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/EmbeddedFolderXmlMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -7,7 +7,6 @@ namespace StructureMap.Source { - [Pluggable("EmbeddedXmlFolder")] public class EmbeddedFolderXmlMementoSource : MementoSource { private readonly string _assemblyName; Modified: trunk/Source/StructureMap/Source/MemoryMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/MemoryMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/MemoryMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -5,7 +5,6 @@ /// <summary> /// An in-memory MementoSource /// </summary> - [Pluggable("Default")] public class MemoryMementoSource : MementoSource { private readonly Hashtable _mementos; Modified: trunk/Source/StructureMap/Source/SingleEmbeddedXmlMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/SingleEmbeddedXmlMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/SingleEmbeddedXmlMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -4,7 +4,6 @@ namespace StructureMap.Source { - [Pluggable("EmbeddedXmlFile")] public class SingleEmbeddedXmlMementoSource : XmlMementoSource { private readonly Assembly _assembly; Modified: trunk/Source/StructureMap/Source/TemplatedMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/TemplatedMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/TemplatedMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -1,6 +1,5 @@ namespace StructureMap.Source { - [Pluggable("Templated")] public class TemplatedMementoSource : MementoSource { private readonly MementoSource _innerSource; Modified: trunk/Source/StructureMap/Source/XmlAttributeFileMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/XmlAttributeFileMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/XmlAttributeFileMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -3,7 +3,6 @@ /// <summary> /// Stores Attribute-normalized InstanceMemento's in an external file /// </summary> - [Pluggable("XmlAttributeFile")] public class XmlAttributeFileMementoSource : XmlFileMementoSource { public XmlAttributeFileMementoSource(string filePath, string xpath, string nodeName) Modified: trunk/Source/StructureMap/Source/XmlFileMementoSource.cs =================================================================== --- trunk/Source/StructureMap/Source/XmlFileMementoSource.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/Source/XmlFileMementoSource.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -8,7 +8,6 @@ /// Implementation of XmlMementoSource that reads InstanceMemento's from an external file. /// Useful to break the StructureMap.config file into smaller pieces. /// </summary> - [Pluggable("XmlFile")] public class XmlFileMementoSource : XmlMementoSource { private readonly string _filePath; Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap/StructureMap.csproj 2008-12-21 16:31:48 UTC (rev 211) @@ -420,6 +420,7 @@ <Compile Include="Pipeline\SmartInstance.cs" /> <Compile Include="PluginTypeConfiguration.cs" /> <Compile Include="ReflectionHelper.cs" /> + <Compile Include="SystemRegistry.cs" /> <Compile Include="Util\Cache.cs" /> </ItemGroup> <ItemGroup> Added: trunk/Source/StructureMap/SystemRegistry.cs =================================================================== --- trunk/Source/StructureMap/SystemRegistry.cs (rev 0) +++ trunk/Source/StructureMap/SystemRegistry.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -0,0 +1,41 @@ +using StructureMap.Attributes; +using StructureMap.Configuration.DSL; +using StructureMap.Pipeline; +using StructureMap.Source; + +namespace StructureMap +{ + public class SystemRegistry : Registry + { + public SystemRegistry() + { + addExpression(graph => graph.AddType(typeof(MementoSource), typeof(XmlFileMementoSource), "XmlFile")); + + ForRequestedType<MementoSource>().TheDefaultIsConcreteType<MemoryMementoSource>(); + AddMementoSourceType<DirectoryXmlMementoSource>("DirectoryXml"); + AddMementoSourceType<EmbeddedFolderXmlMementoSource>("EmbeddedXmlFolder"); + AddMementoSourceType<SingleEmbeddedXmlMementoSource>("EmbeddedXmlFile"); + AddMementoSourceType<TemplatedMementoSource>("Templated"); + AddMementoSourceType<XmlAttributeFileMementoSource>("XmlAttributeFile"); + AddMementoSourceType<XmlFileMementoSource>("XmlFile"); + + + AddInterceptorType<SingletonPolicy>(InstanceScope.Singleton); + AddInterceptorType<ThreadLocalStoragePolicy>(InstanceScope.ThreadLocal); + AddInterceptorType<HttpContextBuildPolicy>(InstanceScope.HttpContext); + AddInterceptorType<HttpSessionBuildPolicy>(InstanceScope.HttpSession); + AddInterceptorType<HybridBuildPolicy>(InstanceScope.Hybrid); + + } + + private void AddMementoSourceType<T>(string name) + { + addExpression(graph => graph.AddType(typeof(MementoSource), typeof(T), name)); + } + + private void AddInterceptorType<T>(InstanceScope scope) + { + addExpression(graph => graph.AddType(typeof(IBuildInterceptor), typeof(T), scope.ToString())); + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/Configuration/NormalGraphBuilderTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/NormalGraphBuilderTester.cs 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap.Testing/Configuration/NormalGraphBuilderTester.cs 2008-12-21 16:31:48 UTC (rev 211) @@ -62,7 +62,6 @@ bool iWasCalled = false; var builder = new GraphBuilder(new Registry[0]); - builder.PrepareSystemObjects(); builder.WithSystemObject<IBuildInterceptor>(memento, "singleton", policy => { Assert.IsInstanceOfType(typeof (SingletonPolicy), policy); Modified: trunk/Source/StructureMap.sln =================================================================== --- trunk/Source/StructureMap.sln 2008-12-21 00:37:33 UTC (rev 210) +++ trunk/Source/StructureMap.sln 2008-12-21 16:31:48 UTC (rev 211) @@ -27,8 +27,6 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Widgets", "Widgets", "{E1C10209-160D-4054-ACB7-478A9FDCF84C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GUI", "GUI", "{4F638ECF-2A69-4D6A-9B68-05CC40951217}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StructureMap", "StructureMap\StructureMap.csproj", "{3F36EA80-2F9A-4DAD-BA27-5AC6163A2EE3}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StructureMap.Testing", "StructureMap.Testing\StructureMap.Testing.csproj", "{63C2742D-B6E2-484F-AFDB-346873075C5E}" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-21 00:37:38
|
Revision: 210 http://structuremap.svn.sourceforge.net/structuremap/?rev=210&view=rev Author: jeremydmiller Date: 2008-12-21 00:37:33 +0000 (Sun, 21 Dec 2008) Log Message: ----------- moved the version up in NAnt Modified Paths: -------------- trunk/cruise.build Modified: trunk/cruise.build =================================================================== --- trunk/cruise.build 2008-12-21 00:34:36 UTC (rev 209) +++ trunk/cruise.build 2008-12-21 00:37:33 UTC (rev 210) @@ -3,7 +3,7 @@ <property name="deployment.dir" value="source\StructureMap.Testing.DeploymentTasks\"/> <property name="results.dir" value="results" /> <property name="nant.dir" value="bin\nant" /> - <property name="project.version" value="2.5.0" /> + <property name="project.version" value="2.5.1" /> <property name="project.config" value="release" /> <property name="archive.dir" value="d:\builds\StructureMap"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-21 00:34:38
|
Revision: 209 http://structuremap.svn.sourceforge.net/structuremap/?rev=209&view=rev Author: jeremydmiller Date: 2008-12-21 00:34:36 +0000 (Sun, 21 Dec 2008) Log Message: ----------- making "EjectAll" work for singletons Modified Paths: -------------- trunk/Source/StructureMap/InstanceFactory.cs trunk/Source/StructureMap/Pipeline/BuildPolicy.cs trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs trunk/Source/StructureMap/Pipeline/IBuildPolicy.cs trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs trunk/Source/StructureMap.Testing/Configuration/DSL/GenericFamilyExpressionTester.cs trunk/Source/StructureMap.Testing/Graph/DynamicInjectionTester.cs trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs trunk/Source/StructureMap.Testing/Pipeline/BuildStrategiesTester.cs Modified: trunk/Source/StructureMap/InstanceFactory.cs =================================================================== --- trunk/Source/StructureMap/InstanceFactory.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap/InstanceFactory.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -87,6 +87,7 @@ public IBuildPolicy Policy { get { return _policy; } + set { _policy = value; } } public void ForEachInstance(Action<Instance> action) @@ -147,6 +148,7 @@ public void EjectAllInstances() { + _policy.EjectAll(); _instances.Clear(); } Modified: trunk/Source/StructureMap/Pipeline/BuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/BuildPolicy.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap/Pipeline/BuildPolicy.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -30,6 +30,12 @@ return this; } + public void EjectAll() + { + // no-op. Unlike other Container's, StructureMap doesn't hang on to + // objects it created as "Transients" + } + #endregion public bool Equals(BuildPolicy obj) Modified: trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -44,6 +44,16 @@ return clonedCache; } + public void EjectAll() + { + ejectAll(); + _innerPolicy.EjectAll(); + } + + protected virtual void ejectAll() + { + } + #endregion protected abstract CacheInterceptor clone(); Modified: trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -45,6 +45,11 @@ } public abstract IBuildPolicy Clone(); + public void EjectAll() + { + _http.EjectAll(); + _nonHttp.EjectAll(); + } } Modified: trunk/Source/StructureMap/Pipeline/IBuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/IBuildPolicy.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap/Pipeline/IBuildPolicy.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -9,5 +9,6 @@ { object Build(BuildSession buildSession, Type pluginType, Instance instance); IBuildPolicy Clone(); + void EjectAll(); } } \ No newline at end of file Modified: trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -1,3 +1,5 @@ +using System; + namespace StructureMap.Pipeline { [Pluggable("Singleton")] @@ -22,6 +24,35 @@ return _cache; } + public InstanceCache Cache + { + get + { + return findCache(); + } + } + + protected override void ejectAll() + { + lock (_locker) + { + _cache.Each(o => + { + IDisposable disposable = o as IDisposable; + if (disposable != null) + { + try + { + disposable.Dispose(); + } + catch (Exception){} + } + }); + + _cache.Clear(); + } + } + protected override CacheInterceptor clone() { return new SingletonPolicy(); Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/CreatePluginFamilyTester.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -289,6 +289,11 @@ throw new NotImplementedException(); } + public void EjectAll() + { + throw new System.NotImplementedException(); + } + #endregion } } \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/GenericFamilyExpressionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/GenericFamilyExpressionTester.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/GenericFamilyExpressionTester.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -61,6 +61,11 @@ throw new NotImplementedException(); } + public void EjectAll() + { + throw new System.NotImplementedException(); + } + #endregion } Modified: trunk/Source/StructureMap.Testing/Graph/DynamicInjectionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/DynamicInjectionTester.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap.Testing/Graph/DynamicInjectionTester.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -364,6 +364,11 @@ throw new NotImplementedException(); } + public void EjectAll() + { + throw new System.NotImplementedException(); + } + #endregion } Modified: trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -1,10 +1,12 @@ using NUnit.Framework; +using Rhino.Mocks; using StructureMap.Attributes; using StructureMap.Configuration.DSL; using StructureMap.Graph; using StructureMap.Pipeline; using StructureMap.Testing.Widget; using StructureMap.Testing.Widget3; +using System.Linq; namespace StructureMap.Testing.Graph { @@ -58,6 +60,23 @@ } [Test] + public void eject_all_instances_removes_all_instances_and_ejects_from_the_build_policy() + { + var factory = new InstanceFactory(typeof (IGateway)); + factory.AddInstance(new SmartInstance<DefaultGateway>()); + factory.AddInstance(new SmartInstance<DefaultGateway>()); + + var policy = MockRepository.GenerateMock<IBuildPolicy>(); + factory.Policy = policy; + + factory.EjectAllInstances(); + + factory.Instances.Count().ShouldEqual(0); + + policy.AssertWasCalled(x => x.EjectAll()); + } + + [Test] public void Import_from_family_picks_up_new_instances() { var factory = new InstanceFactory(typeof (IWidget)); Modified: trunk/Source/StructureMap.Testing/Pipeline/BuildStrategiesTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Pipeline/BuildStrategiesTester.cs 2008-12-20 20:50:53 UTC (rev 208) +++ trunk/Source/StructureMap.Testing/Pipeline/BuildStrategiesTester.cs 2008-12-21 00:34:36 UTC (rev 209) @@ -102,6 +102,7 @@ Assert.IsInstanceOfType(typeof (BuildPolicy), clone.InnerPolicy); } + [Test] public void Singleton_build_policy() { @@ -124,4 +125,81 @@ Assert.AreSame(green1, green3); } } + + [TestFixture] + public class when_the_singleton_policy_ejects_all + { + private SingletonPolicy policy; + private StubBuildPolicy inner; + private StubDisposable disposable1; + private StubDisposable disposable2; + + + [SetUp] + public void SetUp() + { + policy = new SingletonPolicy(); + inner = new StubBuildPolicy(); + policy.InnerPolicy = inner; + + disposable1 = new StubDisposable(); + disposable2 = new StubDisposable(); + + policy.Cache[new InstanceKey() { Name = "a", PluginType = typeof(IGateway) }] = disposable1; + policy.Cache[new InstanceKey() {Name = "b", PluginType = typeof (IGateway)}] = disposable2; + policy.Cache[new InstanceKey() {Name = "c", PluginType = typeof (IGateway)}] = new object(); + + policy.EjectAll(); + } + + [Test] + public void the_count_should_be_zero() + { + policy.Cache.Count.ShouldEqual(0); + } + + [Test] + public void should_have_called_dispose_if_it_was_there() + { + disposable1.DisposedWasCalled.ShouldBeTrue(); + disposable2.DisposedWasCalled.ShouldBeTrue(); + } + + [Test] + public void inner_policy_was_ejected() + { + inner.WasEjected.ShouldBeTrue(); + } + + } + + public class StubDisposable : IDisposable + { + public bool DisposedWasCalled; + + public void Dispose() + { + DisposedWasCalled = true; + } + } + + public class StubBuildPolicy : IBuildPolicy + { + public bool WasEjected; + + public object Build(BuildSession buildSession, Type pluginType, Instance instance) + { + throw new System.NotImplementedException(); + } + + public IBuildPolicy Clone() + { + throw new System.NotImplementedException(); + } + + public void EjectAll() + { + WasEjected = true; + } + } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-20 20:51:14
|
Revision: 208 http://structuremap.svn.sourceforge.net/structuremap/?rev=208&view=rev Author: jeremydmiller Date: 2008-12-20 20:50:53 +0000 (Sat, 20 Dec 2008) Log Message: ----------- adding missed file Added Paths: ----------- trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs Added: trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs (rev 0) +++ trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs 2008-12-20 20:50:53 UTC (rev 208) @@ -0,0 +1,146 @@ +using System; +using System.Collections; +using System.Web; +using System.Web.SessionState; + +namespace StructureMap.Pipeline +{ + public class HttpContextBuildPolicy : CacheInterceptor + { + public static readonly string ITEM_NAME = "STRUCTUREMAP-INSTANCES"; + + public static bool HasContext() + { + return HttpContext.Current != null; + } + + protected override InstanceCache findCache() + { + IDictionary items = findHttpDictionary(); + + if (!items.Contains(ITEM_NAME)) + { + lock (items.SyncRoot) + { + if (!items.Contains(ITEM_NAME)) + { + InstanceCache cache = buildNewCache(); + items.Add(ITEM_NAME, cache); + + return cache; + } + } + } + + return (InstanceCache) items[ITEM_NAME]; + } + + protected virtual IDictionary findHttpDictionary() + { + return HttpContext.Current.Items; + } + + protected override CacheInterceptor clone() + { + return this; + } + } + + public class HttpSessionBuildPolicy : HttpContextBuildPolicy + { + protected override IDictionary findHttpDictionary() + { + return new SessionWrapper(HttpContext.Current.Session); + } + } + + public class SessionWrapper : IDictionary + { + private readonly HttpSessionState _session; + + public SessionWrapper(HttpSessionState session) + { + _session = session; + } + + #region IDictionary Members + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void CopyTo(Array array, int index) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public object SyncRoot + { + get { return _session.SyncRoot; } + } + + public bool IsSynchronized + { + get { throw new NotImplementedException(); } + } + + public bool Contains(object key) + { + return _session[key.ToString()] != null; + } + + public void Add(object key, object value) + { + _session.Add(key.ToString(), value); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public IDictionaryEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + public void Remove(object key) + { + throw new NotImplementedException(); + } + + public object this[object key] + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public ICollection Keys + { + get { throw new NotImplementedException(); } + } + + public ICollection Values + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool IsFixedSize + { + get { throw new NotImplementedException(); } + } + + #endregion + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-20 19:44:09
|
Revision: 207 http://structuremap.svn.sourceforge.net/structuremap/?rev=207&view=rev Author: jeremydmiller Date: 2008-12-20 19:44:05 +0000 (Sat, 20 Dec 2008) Log Message: ----------- allowing users to specify object scope in the Container.Configure() method Modified Paths: -------------- trunk/Source/StructureMap/InstanceFactory.cs trunk/Source/StructureMap/PipelineGraph.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj Added Paths: ----------- trunk/Source/StructureMap/PluginTypeConfiguration.cs trunk/Source/StructureMap.Testing/Bugs/SpecifyScopeInConfigureTester.cs Modified: trunk/Source/StructureMap/InstanceFactory.cs =================================================================== --- trunk/Source/StructureMap/InstanceFactory.cs 2008-12-20 18:50:25 UTC (rev 206) +++ trunk/Source/StructureMap/InstanceFactory.cs 2008-12-20 19:44:05 UTC (rev 207) @@ -16,7 +16,7 @@ new Cache<string, Instance>(delegate { return null; }); private readonly Type _pluginType; - private readonly IBuildPolicy _policy = new BuildPolicy(); + private IBuildPolicy _policy = new BuildPolicy(); #region constructor functions @@ -136,6 +136,12 @@ public void ImportFrom(PluginFamily family) { + if (!_policy.GetType().Equals(family.Policy.GetType())) + { + // TODO: Might need to clear out the existing policy when it's ejected + _policy = family.Policy; + } + family.EachInstance(instance => _instances.Fill(instance.Name, instance)); } Modified: trunk/Source/StructureMap/PipelineGraph.cs =================================================================== --- trunk/Source/StructureMap/PipelineGraph.cs 2008-12-20 18:50:25 UTC (rev 206) +++ trunk/Source/StructureMap/PipelineGraph.cs 2008-12-20 19:44:05 UTC (rev 207) @@ -9,31 +9,6 @@ public delegate InstanceFactory MissingFactoryFunction(Type pluginType, ProfileManager profileManager); - /// <summary> - /// Metadata describing the registration of a PluginType - /// </summary> - public class PluginTypeConfiguration - { - public Type PluginType { get; set; } - - /// <summary> - /// The "instance" that will be used when Container.GetInstance(PluginType) is called. - /// See <see cref="StructureMap.Pipeline.IInstance">IInstance</see> for more information - /// </summary> - public IInstance Default { get; set; } - - /// <summary> - /// The build "policy" for this PluginType. Used by the WhatDoIHave() diagnostics methods - /// </summary> - public IBuildPolicy Policy { get; set; } - - /// <summary> - /// All of the <see cref="StructureMap.Pipeline.IInstance">IInstance</see>'s registered - /// for this PluginType - /// </summary> - public IEnumerable<IInstance> Instances { get; set; } - } - public class PipelineGraph { private readonly Dictionary<Type, IInstanceFactory> _factories Added: trunk/Source/StructureMap/PluginTypeConfiguration.cs =================================================================== --- trunk/Source/StructureMap/PluginTypeConfiguration.cs (rev 0) +++ trunk/Source/StructureMap/PluginTypeConfiguration.cs 2008-12-20 19:44:05 UTC (rev 207) @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using StructureMap.Pipeline; + +namespace StructureMap +{ + /// <summary> + /// Metadata describing the registration of a PluginType + /// </summary> + public class PluginTypeConfiguration + { + public Type PluginType { get; set; } + + /// <summary> + /// The "instance" that will be used when Container.GetInstance(PluginType) is called. + /// See <see cref="StructureMap.Pipeline.IInstance">IInstance</see> for more information + /// </summary> + public IInstance Default { get; set; } + + /// <summary> + /// The build "policy" for this PluginType. Used by the WhatDoIHave() diagnostics methods + /// </summary> + public IBuildPolicy Policy { get; set; } + + /// <summary> + /// All of the <see cref="StructureMap.Pipeline.IInstance">IInstance</see>'s registered + /// for this PluginType + /// </summary> + public IEnumerable<IInstance> Instances { get; set; } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 18:50:25 UTC (rev 206) +++ trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 19:44:05 UTC (rev 207) @@ -418,6 +418,7 @@ <Compile Include="Pipeline\PropertyExpression.cs" /> <Compile Include="Pipeline\SerializedInstance.cs" /> <Compile Include="Pipeline\SmartInstance.cs" /> + <Compile Include="PluginTypeConfiguration.cs" /> <Compile Include="ReflectionHelper.cs" /> <Compile Include="Util\Cache.cs" /> </ItemGroup> Added: trunk/Source/StructureMap.Testing/Bugs/SpecifyScopeInConfigureTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Bugs/SpecifyScopeInConfigureTester.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Bugs/SpecifyScopeInConfigureTester.cs 2008-12-20 19:44:05 UTC (rev 207) @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NUnit.Framework; +using StructureMap.Attributes; +using StructureMap.Testing.Widget3; + +namespace StructureMap.Testing.Bugs +{ + [TestFixture] + public class SpecifyScopeInConfigureTester + { + [Test] + public void specify_the_scope_in_a_Configure_if_it_is_not_already_set() + { + var container = new Container(x => { }); + container.Configure(x => + { + x.ForRequestedType<IGateway>().CacheBy(InstanceScope.Singleton) + .TheDefaultIsConcreteType<DefaultGateway>(); + + }); + + var gateway1 = container.GetInstance<IGateway>(); + var gateway2 = container.GetInstance<IGateway>(); + var gateway3 = container.GetInstance<IGateway>(); + + gateway1.ShouldBeTheSameAs(gateway2); + gateway1.ShouldBeTheSameAs(gateway3); + } + } +} Modified: trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs 2008-12-20 18:50:25 UTC (rev 206) +++ trunk/Source/StructureMap.Testing/Graph/InstanceFactoryTester.cs 2008-12-20 19:44:05 UTC (rev 207) @@ -1,4 +1,5 @@ using NUnit.Framework; +using StructureMap.Attributes; using StructureMap.Configuration.DSL; using StructureMap.Graph; using StructureMap.Pipeline; @@ -74,6 +75,39 @@ } [Test] + public void import_from_another_family_will_override_the_build_policy_if_the_initial_policy_is_the_default() + { + var factory = new InstanceFactory(typeof(IWidget)); + + var family = new PluginFamily(typeof(IWidget)); + family.SetScopeTo(InstanceScope.Singleton); + + factory.ImportFrom(family); + + factory.Policy.ShouldBeOfType<SingletonPolicy>(); + } + + [Test] + public void do_not_replace_the_build_policy_if_it_is_the_same_type_as_the_imported_family() + { + PluginFamily originalFamily = new PluginFamily(typeof(IWidget)); + originalFamily.SetScopeTo(InstanceScope.Singleton); + var factory = new InstanceFactory(originalFamily); + + var originalPolicy = factory.Policy; + + + var family = new PluginFamily(typeof(IWidget)); + family.SetScopeTo(InstanceScope.Singleton); + + factory.ImportFrom(family); + + factory.Policy.ShouldBeTheSameAs(originalPolicy); + } + + + + [Test] public void Merge_from_PluginFamily_will_not_replace_an_existing_instance() { var factory = new InstanceFactory(typeof (IWidget)); Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj =================================================================== --- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2008-12-20 18:50:25 UTC (rev 206) +++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2008-12-20 19:44:05 UTC (rev 207) @@ -180,6 +180,7 @@ <Compile Include="AutoMocking\RhinoMockRepositoryProxyTester.cs" /> <Compile Include="Bugs\IDictionaryAndXmlBugTester.cs" /> <Compile Include="Bugs\ScanIndexerBugTester.cs" /> + <Compile Include="Bugs\SpecifyScopeInConfigureTester.cs" /> <Compile Include="BuildSessionTester.cs" /> <Compile Include="Configuration\ConfigurationParserBuilderTester.cs" /> <Compile Include="Configuration\ConfigurationParserTester.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-20 18:50:31
|
Revision: 206 http://structuremap.svn.sourceforge.net/structuremap/?rev=206&view=rev Author: jeremydmiller Date: 2008-12-20 18:50:25 +0000 (Sat, 20 Dec 2008) Log Message: ----------- Fixed the problem with missing dictionary data in Xml configuration for non-mandatory setters Modified Paths: -------------- trunk/Source/StructureMap/Source/XmlAttributeInstanceMemento.cs trunk/Source/StructureMap/Source/XmlNodeInstanceMemento.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj trunk/Source/StructureMap.Testing/TestData/DataMother.cs Added Paths: ----------- trunk/Source/StructureMap/Extensions.cs trunk/Source/StructureMap.Testing/Bugs/IDictionaryAndXmlBugTester.cs Added: trunk/Source/StructureMap/Extensions.cs =================================================================== --- trunk/Source/StructureMap/Extensions.cs (rev 0) +++ trunk/Source/StructureMap/Extensions.cs 2008-12-20 18:50:25 UTC (rev 206) @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace StructureMap +{ + public static class StringExtensions + { + public static string ToFormat(this string template, params object[] parameters) + { + return string.Format(template, parameters); + } + + public static string[] ToDelimitedArray(this string content) + { + string[] array = content.Split(','); + for (int i = 0; i < array.Length; i++) + { + array[i] = array[i].Trim(); + } + + return array; + } + } +} Modified: trunk/Source/StructureMap/Source/XmlAttributeInstanceMemento.cs =================================================================== --- trunk/Source/StructureMap/Source/XmlAttributeInstanceMemento.cs 2008-12-20 18:16:59 UTC (rev 205) +++ trunk/Source/StructureMap/Source/XmlAttributeInstanceMemento.cs 2008-12-20 18:50:25 UTC (rev 206) @@ -123,7 +123,7 @@ } XmlElement element = _element[name]; - return reader.Read(element, childType); + return element == null ? null : reader.Read(element, childType); } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Source/XmlNodeInstanceMemento.cs =================================================================== --- trunk/Source/StructureMap/Source/XmlNodeInstanceMemento.cs 2008-12-20 18:16:59 UTC (rev 205) +++ trunk/Source/StructureMap/Source/XmlNodeInstanceMemento.cs 2008-12-20 18:50:25 UTC (rev 206) @@ -110,7 +110,7 @@ } XmlElement element = getChildNode(name); - return reader.Read(element, childType); + return element == null ? null : reader.Read(element, childType); } protected override InstanceMemento getChild(string Key) Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 18:16:59 UTC (rev 205) +++ trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 18:50:25 UTC (rev 206) @@ -399,6 +399,7 @@ <Compile Include="Diagnostics\ValidationError.cs" /> <Compile Include="Emitting\Parameters\Methods.cs" /> <Compile Include="ErrorMessages.cs" /> + <Compile Include="Extensions.cs" /> <Compile Include="Graph\FamilyAttributeScanner.cs" /> <Compile Include="Graph\FindAllTypesFilter.cs" /> <Compile Include="Graph\FindRegistriesScanner.cs" /> Added: trunk/Source/StructureMap.Testing/Bugs/IDictionaryAndXmlBugTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Bugs/IDictionaryAndXmlBugTester.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Bugs/IDictionaryAndXmlBugTester.cs 2008-12-20 18:50:25 UTC (rev 206) @@ -0,0 +1,132 @@ +using System.Collections.Generic; +using NUnit.Framework; +using StructureMap.Attributes; +using StructureMap.Testing.TestData; + +namespace StructureMap.Testing.Bugs +{ + [TestFixture] + public class IDictionaryAndXmlBugTester + { + [Test] + public void read_a_dictionary_from_configuration() + { + string className = typeof (ClassWithDictionaryInCtor).AssemblyQualifiedName; + string xml = + @" +<StructureMap> + <DefaultInstance PluginType='{0}' PluggedType='{0}'> + <Property Name='values'> + <Pair Key='color' Value='red'/> + <Pair Key='state' Value='texas'/> + <Pair Key='direction' Value='north'/> + </Property> + </DefaultInstance> +</StructureMap> +" + .ToFormat(className); + + Container container = DataMother.BuildContainerForXml(xml); + + var dict = container.GetInstance<ClassWithDictionaryInCtor>(); + dict.Values["color"].ShouldEqual("red"); + } + + + [Test] + public void + read_a_dictionary_from_configuration_in_attribute_style_that_is_missing_a_dictionary_and_blow_up_with_good_message + () + { + string className = typeof (ClassWithDictionaryInCtor).AssemblyQualifiedName; + string xml = + @" +<StructureMap MementoStyle='Attribute'> + <DefaultInstance PluginType='{0}' PluggedType='{0}'></DefaultInstance> +</StructureMap> +" + .ToFormat(className); + + + try + { + Container container = DataMother.BuildContainerForXml(xml); + container.GetInstance<ClassWithDictionaryInCtor>(); + } + catch (StructureMapException e) + { + e.ErrorCode.ShouldEqual(202); + } + } + + + [Test] + public void + read_a_dictionary_from_configuration_in_attribute_style_that_is_missing_a_dictionary_for_an_optional_setter() + { + string className = typeof (ClassWithDictionaryProperty).AssemblyQualifiedName; + string xml = + @" +<StructureMap MementoStyle='Attribute'> + <DefaultInstance PluginType='{0}' PluggedType='{0}'></DefaultInstance> +</StructureMap> +" + .ToFormat(className); + + + Container container = DataMother.BuildContainerForXml(xml); + container.GetInstance<ClassWithDictionaryProperty>().ShouldNotBeNull(); + } + + [Test] + public void read_a_dictionary_from_configuration_when_the_property_is_missing_on_mandatory_setter() + { + string className = typeof (ClassWithDictionaryProperty2).AssemblyQualifiedName; + string xml = + @" +<StructureMap> + <DefaultInstance PluginType='{0}' PluggedType='{0}'></DefaultInstance> +</StructureMap> +" + .ToFormat(className); + + + try + { + Container container = DataMother.BuildContainerForXml(xml); + container.GetInstance<ClassWithDictionaryProperty2>(); + } + catch (StructureMapException e) + { + e.ErrorCode.ShouldEqual(202); + } + } + + } + + public class ClassWithDictionaryInCtor + { + private readonly IDictionary<string, string> _values; + + public ClassWithDictionaryInCtor(IDictionary<string, string> values) + { + _values = values; + } + + public IDictionary<string, string> Values + { + get { return _values; } + } + } + + public class ClassWithDictionaryProperty + { + public IDictionary<string, string> Values { get; set; } + } + + public class ClassWithDictionaryProperty2 + { + [SetterProperty] + public IDictionary<string, string> Values { get; set; } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj =================================================================== --- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2008-12-20 18:16:59 UTC (rev 205) +++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2008-12-20 18:50:25 UTC (rev 206) @@ -178,6 +178,7 @@ <Compile Include="AutoMocking\MoqFactoryTester.cs" /> <Compile Include="AutoMocking\RhinoAutoMockerTester.cs" /> <Compile Include="AutoMocking\RhinoMockRepositoryProxyTester.cs" /> + <Compile Include="Bugs\IDictionaryAndXmlBugTester.cs" /> <Compile Include="Bugs\ScanIndexerBugTester.cs" /> <Compile Include="BuildSessionTester.cs" /> <Compile Include="Configuration\ConfigurationParserBuilderTester.cs" /> Modified: trunk/Source/StructureMap.Testing/TestData/DataMother.cs =================================================================== --- trunk/Source/StructureMap.Testing/TestData/DataMother.cs 2008-12-20 18:16:59 UTC (rev 205) +++ trunk/Source/StructureMap.Testing/TestData/DataMother.cs 2008-12-20 18:50:25 UTC (rev 206) @@ -17,6 +17,12 @@ { } + public static Container BuildContainerForXml(string xml) + { + var graph = BuildPluginGraphFromXml(xml); + return new Container(graph); + } + public static PluginGraph BuildPluginGraphFromXml(string xml) { XmlDocument document = BuildDocument(xml); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-20 18:17:03
|
Revision: 205 http://structuremap.svn.sourceforge.net/structuremap/?rev=205&view=rev Author: jeremydmiller Date: 2008-12-20 18:16:59 +0000 (Sat, 20 Dec 2008) Log Message: ----------- added a new caching strategy for Session Modified Paths: -------------- trunk/Source/StructureMap/Attributes/InstanceScope.cs trunk/Source/StructureMap/Graph/PluginFamily.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs Removed Paths: ------------- trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs Modified: trunk/Source/StructureMap/Attributes/InstanceScope.cs =================================================================== --- trunk/Source/StructureMap/Attributes/InstanceScope.cs 2008-12-20 17:59:45 UTC (rev 204) +++ trunk/Source/StructureMap/Attributes/InstanceScope.cs 2008-12-20 18:16:59 UTC (rev 205) @@ -6,6 +6,7 @@ Singleton, ThreadLocal, HttpContext, - Hybrid + Hybrid, + HttpSession } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/PluginFamily.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginFamily.cs 2008-12-20 17:59:45 UTC (rev 204) +++ trunk/Source/StructureMap/Graph/PluginFamily.cs 2008-12-20 18:16:59 UTC (rev 205) @@ -77,6 +77,10 @@ case InstanceScope.Hybrid: AddInterceptor(new HybridBuildPolicy()); break; + + case InstanceScope.HttpSession: + AddInterceptor(new HttpSessionBuildPolicy()); + break; } } Deleted: trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs 2008-12-20 17:59:45 UTC (rev 204) +++ trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs 2008-12-20 18:16:59 UTC (rev 205) @@ -1,41 +0,0 @@ -using System.Collections; -using System.Web; - -namespace StructureMap.Pipeline -{ - public class HttpContextBuildPolicy : CacheInterceptor - { - public static readonly string ITEM_NAME = "STRUCTUREMAP-INSTANCES"; - - public static bool HasContext() - { - return HttpContext.Current != null; - } - - protected override InstanceCache findCache() - { - IDictionary items = HttpContext.Current.Items; - - if (!items.Contains(ITEM_NAME)) - { - lock (items.SyncRoot) - { - if (!items.Contains(ITEM_NAME)) - { - InstanceCache cache = buildNewCache(); - items.Add(ITEM_NAME, cache); - - return cache; - } - } - } - - return (InstanceCache) items[ITEM_NAME]; - } - - protected override CacheInterceptor clone() - { - return this; - } - } -} \ No newline at end of file Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 17:59:45 UTC (rev 204) +++ trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 18:16:59 UTC (rev 205) @@ -411,7 +411,7 @@ <Compile Include="Pipeline\BuildFrame.cs" /> <Compile Include="Pipeline\BuildStack.cs" /> <Compile Include="Pipeline\ConfiguredInstanceBase.cs" /> - <Compile Include="Pipeline\HttpContextBuildStorage.cs" /> + <Compile Include="Pipeline\HttpContextBuildPolicy.cs" /> <Compile Include="Pipeline\InstanceKey.cs" /> <Compile Include="Pipeline\IStructuredInstance.cs" /> <Compile Include="Pipeline\PropertyExpression.cs" /> Modified: trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs 2008-12-20 17:59:45 UTC (rev 204) +++ trunk/Source/StructureMap.Testing/Graph/PluginFamilyTester.cs 2008-12-20 18:16:59 UTC (rev 205) @@ -260,6 +260,15 @@ } [Test] + public void set_the_scope_to_session() + { + var family = new PluginFamily(typeof(IServiceProvider)); + family.SetScopeTo(InstanceScope.HttpSession); + + family.Policy.ShouldBeOfType<HttpSessionBuildPolicy>(); + } + + [Test] public void SetScopeToSingleton() { var family = new PluginFamily(typeof (IServiceProvider)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-20 17:59:49
|
Revision: 204 http://structuremap.svn.sourceforge.net/structuremap/?rev=204&view=rev Author: jeremydmiller Date: 2008-12-20 17:59:45 +0000 (Sat, 20 Dec 2008) Log Message: ----------- Refactored the BuildPolicy caching strategies to use the Cache object and make it easier to add new types of CacheInterceptor Modified Paths: -------------- trunk/Source/CommonAssemblyInfo.cs trunk/Source/StructureMap/BuildSession.cs trunk/Source/StructureMap/Emitting/Parameters/Methods.cs trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs trunk/Source/StructureMap/Graph/PluginCache.cs trunk/Source/StructureMap/Graph/PluginFamily.cs trunk/Source/StructureMap/Graph/SetterProperty.cs trunk/Source/StructureMap/InstanceFactory.cs trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs trunk/Source/StructureMap/Pipeline/ThreadLocalStoragePolicy.cs trunk/Source/StructureMap/StructureMap.csproj trunk/Source/StructureMap/Util/Cache.cs trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj Added Paths: ----------- trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs trunk/Source/StructureMap/Pipeline/InstanceKey.cs trunk/Source/StructureMap.Testing/Bugs/ trunk/Source/StructureMap.Testing/Bugs/ScanIndexerBugTester.cs Removed Paths: ------------- trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs Modified: trunk/Source/CommonAssemblyInfo.cs =================================================================== --- trunk/Source/CommonAssemblyInfo.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/CommonAssemblyInfo.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -14,9 +14,10 @@ [assembly: ComVisibleAttribute(false)] [assembly: AssemblyVersionAttribute("2.5.0.0000")] -[assembly: AssemblyCopyrightAttribute("Copyright (c) 2007, Jeremy D. Miller")] +[assembly: AssemblyCopyrightAttribute("Copyright (c) 2003-2008, Jeremy D. Miller")] [assembly: AssemblyProductAttribute("StructureMap")] [assembly: AssemblyCompanyAttribute("")] [assembly: AssemblyConfigurationAttribute("release")] [assembly: AssemblyInformationalVersionAttribute("2.5.0.0000")] +[assembly: AssemblyFileVersionAttribute("2.5.0.0000")] Modified: trunk/Source/StructureMap/BuildSession.cs =================================================================== --- trunk/Source/StructureMap/BuildSession.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/BuildSession.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -142,7 +142,7 @@ public virtual object CreateInstance(Type pluginType) { - return _defaults.Retrieve(pluginType); + return _defaults[pluginType]; } public virtual object ApplyInterception(Type pluginType, object actualValue) @@ -153,7 +153,7 @@ public virtual void RegisterDefault(Type pluginType, object defaultObject) { - _defaults.Store(pluginType, defaultObject); + _defaults[pluginType] = defaultObject; } Modified: trunk/Source/StructureMap/Emitting/Parameters/Methods.cs =================================================================== --- trunk/Source/StructureMap/Emitting/Parameters/Methods.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Emitting/Parameters/Methods.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -39,7 +39,7 @@ public static MethodInfo ParseFor(Type type) { - return _parseMethods.Retrieve(type); + return _parseMethods[type]; } } } \ No newline at end of file Modified: trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs =================================================================== --- trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Graph/GenericsPluginGraph.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -81,7 +81,7 @@ public void AddFamily(PluginFamily family) { - _families.Store(family.PluginType, family); + _families[family.PluginType] = family; } @@ -91,7 +91,7 @@ if (_families.Has(basicType)) { - PluginFamily basicFamily = _families.Retrieve(basicType); + PluginFamily basicFamily = _families[basicType]; Type[] templatedParameterTypes = templatedType.GetGenericArguments(); @@ -158,7 +158,7 @@ public PluginFamily FindFamily(Type pluginType) { - return _families.Retrieve(pluginType); + return _families[pluginType]; } public bool HasFamily(Type pluginType) Modified: trunk/Source/StructureMap/Graph/PluginCache.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginCache.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Graph/PluginCache.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -17,7 +17,7 @@ _plugins = new Cache<Type, Plugin>(t => new Plugin(t)); _builders = new Cache<Type, InstanceBuilder>(t => { - Plugin plugin = _plugins.Retrieve(t); + Plugin plugin = _plugins[t]; plugin.SetFilledTypes(_filledTypes); return new InstanceBuilderAssembly(new[] {plugin}).Compile()[0]; }); @@ -25,12 +25,12 @@ public static Plugin GetPlugin(Type pluggedType) { - return _plugins.Retrieve(pluggedType); + return _plugins[pluggedType]; } public static InstanceBuilder FindBuilder(Type pluggedType) { - return _builders.Retrieve(pluggedType); + return _builders[pluggedType]; } public static void Compile() @@ -51,7 +51,7 @@ } var assembly = new InstanceBuilderAssembly(plugins); - assembly.Compile().ForEach(b => _builders.Store(b.PluggedType, b)); + assembly.Compile().ForEach(b => _builders[b.PluggedType] = b); } private static bool pluginHasNoBuilder(Plugin plugin) @@ -61,7 +61,7 @@ public static void Store(Type pluggedType, InstanceBuilder builder) { - _builders.Store(pluggedType, builder); + _builders[pluggedType] = builder; } internal static void ResetAll() Modified: trunk/Source/StructureMap/Graph/PluginFamily.cs =================================================================== --- trunk/Source/StructureMap/Graph/PluginFamily.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Graph/PluginFamily.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -95,7 +95,7 @@ public void AddInstance(Instance instance) { - _instances.Store(instance.Name, instance); + _instances[instance.Name] = instance; } @@ -170,7 +170,7 @@ public Instance GetInstance(string name) { - return _instances.Retrieve(name); + return _instances[name]; } public bool HasPlugin(Type pluggedType) @@ -196,7 +196,7 @@ assertPluggability(pluggedType); Plugin plugin = PluginCache.GetPlugin(pluggedType); - _pluggedTypes.Store(plugin.ConcreteKey, plugin); + _pluggedTypes[plugin.ConcreteKey] = plugin; return plugin; } @@ -206,7 +206,7 @@ assertPluggability(pluggedType); Plugin plugin = PluginCache.GetPlugin(pluggedType); - _pluggedTypes.Store(key, plugin); + _pluggedTypes[key] = plugin; return plugin; } @@ -263,7 +263,7 @@ { if (_pluggedTypes.Has(concreteKey)) { - return _pluggedTypes.Retrieve(concreteKey); + return _pluggedTypes[concreteKey]; } return null; Modified: trunk/Source/StructureMap/Graph/SetterProperty.cs =================================================================== --- trunk/Source/StructureMap/Graph/SetterProperty.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Graph/SetterProperty.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -41,6 +41,9 @@ { Type propertyType = _property.PropertyType; + // Ignore indexer properties + if (_property.GetIndexParameters().Length > 0) return; + if (IsPrimitive(propertyType)) visitor.PrimitiveSetter(_property, IsMandatory); if (IsChild(propertyType)) visitor.ChildSetter(_property, IsMandatory); if (IsChildArray(propertyType)) visitor.ChildArraySetter(_property, IsMandatory); Modified: trunk/Source/StructureMap/InstanceFactory.cs =================================================================== --- trunk/Source/StructureMap/InstanceFactory.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/InstanceFactory.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -96,7 +96,7 @@ public void AddInstance(Instance instance) { - _instances.Store(instance.Name, instance); + _instances[instance.Name] = instance; } @@ -131,7 +131,7 @@ public Instance FindInstance(string name) { - return _instances.Retrieve(name); + return _instances[name]; } public void ImportFrom(PluginFamily family) Modified: trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Pipeline/CacheInterceptor.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -1,7 +1,15 @@ using System; +using StructureMap.Util; namespace StructureMap.Pipeline { + public class InstanceCache : Cache<InstanceKey, object> + { + public InstanceCache(IBuildPolicy innerPolicy) : base(key => innerPolicy.Build(key.Session, key.PluginType, key.Instance)) + { + } + } + public abstract class CacheInterceptor : IBuildInterceptor { private readonly object _locker = new object(); @@ -15,22 +23,17 @@ set { _innerPolicy = value; } } + protected InstanceCache buildNewCache() + { + return new InstanceCache(_innerPolicy); + } + protected abstract InstanceCache findCache(); + public object Build(BuildSession buildSession, Type pluginType, Instance instance) { - if (!isCached(instance.Name, pluginType)) - { - lock (_locker) - { - if (!isCached(instance.Name, pluginType)) - { - object returnValue = _innerPolicy.Build(buildSession, pluginType, instance); - storeInCache(instance.Name, pluginType, returnValue); - } - } - } - - return retrieveFromCache(instance.Name, pluginType); + var key = new InstanceKey{Instance = instance, PluginType = pluginType, Session = buildSession}; + return findCache()[key]; } public IBuildPolicy Clone() @@ -45,10 +48,6 @@ protected abstract CacheInterceptor clone(); - protected abstract void storeInCache(string instanceKey, Type pluginType, object instance); - protected abstract bool isCached(string instanceKey, Type pluginType); - protected abstract object retrieveFromCache(string instanceKey, Type pluginType); - public override string ToString() { return GetType().FullName + " / " + _innerPolicy; Deleted: trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Pipeline/HttpContextBuildPolicy.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -1,41 +0,0 @@ -using System; -using System.Web; - -namespace StructureMap.Pipeline -{ - public class HttpContextBuildPolicy : CacheInterceptor - { - private string _prefix = Guid.NewGuid().ToString(); - - - public static bool HasContext() - { - return HttpContext.Current != null; - } - - protected override void storeInCache(string instanceKey, Type pluginType, object instance) - { - HttpContext.Current.Items.Add(getKey(instanceKey, pluginType), instance); - } - - protected override bool isCached(string instanceKey, Type pluginType) - { - return HttpContext.Current.Items.Contains(getKey(instanceKey, pluginType)); - } - - protected override object retrieveFromCache(string instanceKey, Type pluginType) - { - return HttpContext.Current.Items[getKey(instanceKey, pluginType)]; - } - - private string getKey(string instanceKey, Type pluginType) - { - return string.Format("{0}:{1}:{2}", pluginType.AssemblyQualifiedName, instanceKey, _prefix); - } - - protected override CacheInterceptor clone() - { - return this; - } - } -} \ No newline at end of file Added: trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs (rev 0) +++ trunk/Source/StructureMap/Pipeline/HttpContextBuildStorage.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -0,0 +1,41 @@ +using System.Collections; +using System.Web; + +namespace StructureMap.Pipeline +{ + public class HttpContextBuildPolicy : CacheInterceptor + { + public static readonly string ITEM_NAME = "STRUCTUREMAP-INSTANCES"; + + public static bool HasContext() + { + return HttpContext.Current != null; + } + + protected override InstanceCache findCache() + { + IDictionary items = HttpContext.Current.Items; + + if (!items.Contains(ITEM_NAME)) + { + lock (items.SyncRoot) + { + if (!items.Contains(ITEM_NAME)) + { + InstanceCache cache = buildNewCache(); + items.Add(ITEM_NAME, cache); + + return cache; + } + } + } + + return (InstanceCache) items[ITEM_NAME]; + } + + protected override CacheInterceptor clone() + { + return this; + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Pipeline/HybridBuildPolicy.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -2,15 +2,17 @@ namespace StructureMap.Pipeline { - public class HybridBuildPolicy : IBuildInterceptor + public abstract class HttpBuildPolicyBase<HTTP, NONHTTP> : IBuildInterceptor + where HTTP : IBuildInterceptor, new() + where NONHTTP : IBuildInterceptor, new() { private readonly IBuildInterceptor _http; - private readonly IBuildInterceptor _threadLocal; + private readonly IBuildInterceptor _nonHttp; - public HybridBuildPolicy() + public HttpBuildPolicyBase() { - _http = new HttpContextBuildPolicy(); - _threadLocal = new ThreadLocalStoragePolicy(); + _http = new HTTP(); + _nonHttp = new NONHTTP(); } private IBuildPolicy _innerPolicy; @@ -22,19 +24,17 @@ { return HttpContextBuildPolicy.HasContext() ? _http - : _threadLocal; + : _nonHttp; } } - #region IBuildInterceptor Members - public IBuildPolicy InnerPolicy { get { return _innerPolicy; } set { _http.InnerPolicy = value; - _threadLocal.InnerPolicy = value; + _nonHttp.InnerPolicy = value; _innerPolicy = value; } } @@ -44,14 +44,16 @@ return interceptor.Build(buildSession, pluginType, instance); } - public IBuildPolicy Clone() + public abstract IBuildPolicy Clone(); + } + + + public class HybridBuildPolicy : HttpBuildPolicyBase<HttpContextBuildPolicy, ThreadLocalStoragePolicy> + { + public override IBuildPolicy Clone() { - var policy = new HybridBuildPolicy(); - policy.InnerPolicy = _innerPolicy.Clone(); - - return policy; + return new HybridBuildPolicy(){InnerPolicy = InnerPolicy.Clone()}; } + } - #endregion - } } \ No newline at end of file Added: trunk/Source/StructureMap/Pipeline/InstanceKey.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/InstanceKey.cs (rev 0) +++ trunk/Source/StructureMap/Pipeline/InstanceKey.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -0,0 +1,60 @@ +using System; + +namespace StructureMap.Pipeline +{ + public class InstanceKey + { + public string Name { get; set; } + public Type PluginType { get; set; } + private WeakReference _session; + private WeakReference _instance; + + public InstanceKey() + { + } + + + + public BuildSession Session + { + get { return (BuildSession) _session.Target; } + set { _session = new WeakReference(value); } + } + + public Instance Instance + { + get + { + return (Instance) _instance.Target; + } + set + { + Name = value.Name; + _instance = new WeakReference(value); + } + } + + public bool Equals(InstanceKey obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return Equals(obj.Name, Name) && Equals(obj.PluginType, PluginType); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != typeof(InstanceKey)) return false; + return Equals((InstanceKey)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((Name != null ? Name.GetHashCode() : 0) * 397) ^ (PluginType != null ? PluginType.GetHashCode() : 0); + } + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Pipeline/SingletonPolicy.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -1,28 +1,27 @@ -using System; -using System.Collections.Generic; - namespace StructureMap.Pipeline { [Pluggable("Singleton")] public class SingletonPolicy : CacheInterceptor { - private readonly Dictionary<string, object> _instances = new Dictionary<string, object>(); + private readonly object _locker = new object(); + private InstanceCache _cache; - protected override void storeInCache(string instanceKey, Type pluginType, object instance) + protected override InstanceCache findCache() { - _instances.Add(instanceKey, instance); - } + if (_cache == null) + { + lock (_locker) + { + if (_cache == null) + { + _cache = buildNewCache(); + } + } + } - protected override bool isCached(string instanceKey, Type pluginType) - { - return _instances.ContainsKey(instanceKey); + return _cache; } - protected override object retrieveFromCache(string instanceKey, Type pluginType) - { - return _instances[instanceKey]; - } - protected override CacheInterceptor clone() { return new SingletonPolicy(); Modified: trunk/Source/StructureMap/Pipeline/ThreadLocalStoragePolicy.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/ThreadLocalStoragePolicy.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Pipeline/ThreadLocalStoragePolicy.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -1,48 +1,32 @@ using System; -using System.Collections.Generic; namespace StructureMap.Pipeline { public class ThreadLocalStoragePolicy : CacheInterceptor { - [ThreadStatic] private static Dictionary<string, object> _instances; + [ThreadStatic] private static InstanceCache _cache; private readonly object _locker = new object(); private void guaranteeHashExists() { - if (_instances == null) + if (_cache == null) { lock (_locker) { - if (_instances == null) + if (_cache == null) { - _instances = new Dictionary<string, object>(); + _cache = buildNewCache(); } } } } - protected override void storeInCache(string instanceKey, Type pluginType, object instance) + protected override InstanceCache findCache() { - _instances.Add(getKey(instanceKey, pluginType), instance); - } - - protected override bool isCached(string instanceKey, Type pluginType) - { guaranteeHashExists(); - return _instances.ContainsKey(getKey(instanceKey, pluginType)); + return _cache; } - protected override object retrieveFromCache(string instanceKey, Type pluginType) - { - return _instances[getKey(instanceKey, pluginType)]; - } - - private string getKey(string instanceKey, Type pluginType) - { - return string.Format("{0}:{1}", pluginType.AssemblyQualifiedName, instanceKey); - } - protected override CacheInterceptor clone() { return this; Modified: trunk/Source/StructureMap/StructureMap.csproj =================================================================== --- trunk/Source/StructureMap/StructureMap.csproj 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/StructureMap.csproj 2008-12-20 17:59:45 UTC (rev 204) @@ -167,7 +167,6 @@ <Compile Include="Pipeline\ConfiguredInstance.Expressions.cs" /> <Compile Include="Pipeline\ConstructorInstance.cs" /> <Compile Include="Pipeline\DefaultInstance.cs" /> - <Compile Include="Pipeline\HttpContextBuildPolicy.cs" /> <Compile Include="Pipeline\HybridBuildPolicy.cs" /> <Compile Include="Pipeline\IBuildInterceptor.cs" /> <Compile Include="Pipeline\IBuildPolicy.cs" /> @@ -412,6 +411,8 @@ <Compile Include="Pipeline\BuildFrame.cs" /> <Compile Include="Pipeline\BuildStack.cs" /> <Compile Include="Pipeline\ConfiguredInstanceBase.cs" /> + <Compile Include="Pipeline\HttpContextBuildStorage.cs" /> + <Compile Include="Pipeline\InstanceKey.cs" /> <Compile Include="Pipeline\IStructuredInstance.cs" /> <Compile Include="Pipeline\PropertyExpression.cs" /> <Compile Include="Pipeline\SerializedInstance.cs" /> Modified: trunk/Source/StructureMap/Util/Cache.cs =================================================================== --- trunk/Source/StructureMap/Util/Cache.cs 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap/Util/Cache.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -6,26 +6,43 @@ { public class Cache<KEY, VALUE> : IEnumerable<VALUE> where VALUE : class { - private readonly Func<KEY, VALUE> _onMissing = key => + private readonly object _locker = new object(); + private readonly IDictionary<KEY, VALUE> _values; + + private Func<VALUE, KEY> _getKey = delegate { throw new NotImplementedException(); }; + + private Func<KEY, VALUE> _onMissing = delegate(KEY key) { string message = string.Format("Key '{0}' could not be found", key); throw new KeyNotFoundException(message); }; - private readonly Dictionary<KEY, VALUE> _values = new Dictionary<KEY, VALUE>(); - - private Func<VALUE, KEY> _getKey = delegate { throw new NotImplementedException(); }; - private readonly object _valuesLock = new object(); - public Cache() + : this(new Dictionary<KEY, VALUE>()) { } public Cache(Func<KEY, VALUE> onMissing) + : this(new Dictionary<KEY, VALUE>(), onMissing) { + } + + public Cache(IDictionary<KEY, VALUE> dictionary, Func<KEY, VALUE> onMissing) + : this(dictionary) + { _onMissing = onMissing; } + public Cache(IDictionary<KEY, VALUE> dictionary) + { + _values = dictionary; + } + + public Func<KEY, VALUE> OnMissing + { + set { _onMissing = value; } + } + public Func<VALUE, KEY> GetKey { get { return _getKey; } @@ -50,11 +67,43 @@ } } + + public VALUE this[KEY key] + { + get + { + if (!_values.ContainsKey(key)) + { + lock (_locker) + { + if (!_values.ContainsKey(key)) + { + VALUE value = _onMissing(key); + _values.Add(key, value); + } + } + } + + return _values[key]; + } + set + { + if (_values.ContainsKey(key)) + { + _values[key] = value; + } + else + { + _values.Add(key, value); + } + } + } + #region IEnumerable<VALUE> Members IEnumerator IEnumerable.GetEnumerator() { - return ((IEnumerable<VALUE>) this).GetEnumerator(); + return ((IEnumerable<VALUE>)this).GetEnumerator(); } public IEnumerator<VALUE> GetEnumerator() @@ -64,16 +113,6 @@ #endregion - public void Clear() - { - _values.Clear(); - } - - public void Store(KEY key, VALUE value) - { - _values[key] = value; - } - public void Fill(KEY key, VALUE value) { if (_values.ContainsKey(key)) @@ -84,22 +123,17 @@ _values.Add(key, value); } - public VALUE Retrieve(KEY key) + public bool TryRetrieve(KEY key, out VALUE value) { - if (!_values.ContainsKey(key)) + value = default(VALUE); + + if (_values.ContainsKey(key)) { - lock (_valuesLock) - { - if (!_values.ContainsKey(key)) - { - // Potential deadlock if _onMissing attempts to retrieve the same key - VALUE value = _onMissing(key); - _values.Add(key, value); - } - } + value = _values[key]; + return true; } - return _values[key]; + return false; } public void Each(Action<VALUE> action) @@ -127,7 +161,7 @@ { bool returnValue = false; - Each(value => returnValue |= predicate(value)); + Each(delegate(VALUE value) { returnValue |= predicate(value); }); return returnValue; } @@ -155,7 +189,15 @@ public void Remove(KEY key) { - _values.Remove(key); + if (_values.ContainsKey(key)) + { + _values.Remove(key); + } } + + public void Clear() + { + _values.Clear(); + } } } \ No newline at end of file Added: trunk/Source/StructureMap.Testing/Bugs/ScanIndexerBugTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Bugs/ScanIndexerBugTester.cs (rev 0) +++ trunk/Source/StructureMap.Testing/Bugs/ScanIndexerBugTester.cs 2008-12-20 17:59:45 UTC (rev 204) @@ -0,0 +1,31 @@ +using NUnit.Framework; + +namespace StructureMap.Testing.Bugs +{ + [TestFixture] + public class ScanIndexerBugTester + { + [Test] + public void do_not_blow_up_on_scanning_the_property_for_indexer() + { + var container = new Container(); + container.GetInstance<ClassWithIndexer>().ShouldNotBeNull(); + } + } + + public class ClassWithIndexer + { + + public string this[string key] + { + get + { + return key; + } + set + { + + } + } + } +} \ No newline at end of file Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj =================================================================== --- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2008-12-19 19:04:47 UTC (rev 203) +++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2008-12-20 17:59:45 UTC (rev 204) @@ -1,7 +1,7 @@ <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5"> <PropertyGroup> <ProjectType>Local</ProjectType> - <ProductVersion>9.0.30729</ProductVersion> + <ProductVersion>9.0.21022</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{63C2742D-B6E2-484F-AFDB-346873075C5E}</ProjectGuid> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> @@ -178,6 +178,7 @@ <Compile Include="AutoMocking\MoqFactoryTester.cs" /> <Compile Include="AutoMocking\RhinoAutoMockerTester.cs" /> <Compile Include="AutoMocking\RhinoMockRepositoryProxyTester.cs" /> + <Compile Include="Bugs\ScanIndexerBugTester.cs" /> <Compile Include="BuildSessionTester.cs" /> <Compile Include="Configuration\ConfigurationParserBuilderTester.cs" /> <Compile Include="Configuration\ConfigurationParserTester.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jer...@us...> - 2008-12-19 19:04:51
|
Revision: 203 http://structuremap.svn.sourceforge.net/structuremap/?rev=203&view=rev Author: jeremydmiller Date: 2008-12-19 19:04:47 +0000 (Fri, 19 Dec 2008) Log Message: ----------- fixing a bug reported in: http://groups.google.com/group/structuremap-users/browse_thread/thread/1ab08ef6c3ac6bf1?hl=en Modified Paths: -------------- trunk/Source/StructureMap/Container.cs trunk/Source/StructureMap/Pipeline/ConfiguredInstanceBase.cs trunk/Source/StructureMap/Pipeline/ExplicitArguments.cs trunk/Source/StructureMap.Testing/Configuration/DSL/ProfileExpressionTester.cs trunk/Source/StructureMap.Testing/GenericsIntegrationTester.cs trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs Modified: trunk/Source/StructureMap/Container.cs =================================================================== --- trunk/Source/StructureMap/Container.cs 2008-12-19 15:46:37 UTC (rev 202) +++ trunk/Source/StructureMap/Container.cs 2008-12-19 19:04:47 UTC (rev 203) @@ -109,7 +109,9 @@ { Instance defaultInstance = _pipelineGraph.GetDefault(pluginType); - Instance instance = new ExplicitInstance(pluginType, args, defaultInstance); + BasicInstance basicInstance = defaultInstance as BasicInstance; + + Instance instance = basicInstance == null ? defaultInstance : new ExplicitInstance(pluginType, args, basicInstance); BuildSession session = withNewSession(); args.RegisterDefaults(session); Modified: trunk/Source/StructureMap/Pipeline/ConfiguredInstanceBase.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/ConfiguredInstanceBase.cs 2008-12-19 15:46:37 UTC (rev 202) +++ trunk/Source/StructureMap/Pipeline/ConfiguredInstanceBase.cs 2008-12-19 19:04:47 UTC (rev 203) @@ -4,7 +4,7 @@ namespace StructureMap.Pipeline { - public interface Copyable + public interface BasicInstance { Type PluggedType { get; } Dictionary<string, string> Properties { get; } @@ -13,7 +13,7 @@ } - public abstract class ConfiguredInstanceBase<T> : Instance, IConfiguredInstance, IStructuredInstance, Copyable + public abstract class ConfiguredInstanceBase<T> : Instance, IConfiguredInstance, IStructuredInstance, BasicInstance { protected Dictionary<string, Instance[]> _arrays = new Dictionary<string, Instance[]>(); protected Dictionary<string, Instance> _children = new Dictionary<string, Instance>(); @@ -42,22 +42,22 @@ #region Copyable Members - Type Copyable.PluggedType + Type BasicInstance.PluggedType { get { return _pluggedType; } } - Dictionary<string, string> Copyable.Properties + Dictionary<string, string> BasicInstance.Properties { get { return _properties; } } - Dictionary<string, Instance> Copyable.Children + Dictionary<string, Instance> BasicInstance.Children { get { return _children; } } - Dictionary<string, Instance[]> Copyable.Arrays + Dictionary<string, Instance[]> BasicInstance.Arrays { get { return _arrays; } } @@ -241,7 +241,7 @@ _properties[propertyName] = propertyValue; } - protected void mergeIntoThis(Copyable instance) + protected void mergeIntoThis(BasicInstance instance) { _pluggedType = instance.PluggedType; Modified: trunk/Source/StructureMap/Pipeline/ExplicitArguments.cs =================================================================== --- trunk/Source/StructureMap/Pipeline/ExplicitArguments.cs 2008-12-19 15:46:37 UTC (rev 202) +++ trunk/Source/StructureMap/Pipeline/ExplicitArguments.cs 2008-12-19 19:04:47 UTC (rev 203) @@ -76,20 +76,11 @@ { private readonly ExplicitArguments _args; - public ExplicitInstance(Type pluginType, ExplicitArguments args, Instance defaultInstance) : base(null) + public ExplicitInstance(Type pluginType, ExplicitArguments args, BasicInstance defaultInstance) : base(null) { args.Configure(this); _args = args; - - var defaultConfiguration = defaultInstance as Copyable; - if (defaultConfiguration != null) - { - mergeIntoThis(defaultConfiguration); - } - else - { - setPluggedType(pluginType); - } + mergeIntoThis(defaultInstance); } Modified: trunk/Source/StructureMap.Testing/Configuration/DSL/ProfileExpressionTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/Configuration/DSL/ProfileExpressionTester.cs 2008-12-19 15:46:37 UTC (rev 202) +++ trunk/Source/StructureMap.Testing/Configuration/DSL/ProfileExpressionTester.cs 2008-12-19 19:04:47 UTC (rev 203) @@ -40,7 +40,7 @@ { string theProfileName = "something"; - IContainer manager = new Container(registry => + IContainer container = new Container(registry => { registry.CreateProfile(theProfileName, x => { @@ -49,10 +49,10 @@ }); }); - manager.SetDefaultsToProfile(theProfileName); + container.SetDefaultsToProfile(theProfileName); - Assert.IsInstanceOfType(typeof(AWidget), manager.GetInstance<IWidget>()); - Assert.IsInstanceOfType(typeof(DefaultRule), manager.GetInstance<Rule>()); + Assert.IsInstanceOfType(typeof(AWidget), container.GetInstance<IWidget>()); + Assert.IsInstanceOfType(typeof(DefaultRule), container.GetInstance<Rule>()); } Modified: trunk/Source/StructureMap.Testing/GenericsIntegrationTester.cs =================================================================== --- trunk/Source/StructureMap.Testing/GenericsIntegrationTester.cs 2008-12-19 15:46:37 UTC (rev 202) +++ trunk/Source/StructureMap.Testing/GenericsIntegrationTester.cs 2008-12-19 19:04:47 UTC (rev 203) @@ -1,5 +1,6 @@ using System.Collections; using NUnit.Framework; +using StructureMap.Configuration.DSL; using StructureMap.Graph; using StructureMap.Testing.GenericWidgets; using StructureMap.Testing.TestData; @@ -74,6 +75,20 @@ (IService<double>) manager.GetInstance(typeof (IService<double>), "Default"); } + + + + + + + + + + + + + + [Test] public void PicksUpAnExplicitlyDefinedGenericPluginFamilyFromConfiguration() { Modified: trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs =================================================================== --- trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs 2008-12-19 15:46:37 UTC (rev 202) +++ trunk/Source/StructureMap.Testing/Graph/TestExplicitArguments.cs 2008-12-19 19:04:47 UTC (rev 203) @@ -1,5 +1,7 @@ +using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using NUnit.Framework; using StructureMap.Pipeline; using StructureMap.Testing.Pipeline; @@ -96,13 +98,58 @@ } [Test] + public void use_a_type_that_is_not_part_of_the_constructor_in_the_with() + { + var container = new Container(); + container.With(new Address()).GetInstance<ClassWithNoArgs>() + .ShouldBeOfType<ClassWithNoArgs>(); + } + + [Test] + public void use_explicit_type_arguments_with_custom_instance() + { + var container = new Container(x => + { + x.ForRequestedType<ClassWithNoArgs>().TheDefault.IsThis(new SpecialInstance()); + }); + + Debug.WriteLine(container.WhatDoIHave()); + + var address = new Address(); + + + container.With(address).GetInstance<ClassWithNoArgs>() + .TheAddress.ShouldBeTheSameAs(address); + + } + + public class ClassWithNoArgs + { + public Address TheAddress { get; set;} + } + public class Address{} + + public class SpecialInstance : Instance + { + protected override string getDescription() + { + return string.Empty; + } + + protected override object build(Type pluginType, BuildSession session) + { + return new ClassWithNoArgs() {TheAddress = (Address)session.CreateInstance(typeof (Address))}; + } + } + + [Test] public void ExplicitArguments_can_return_child_by_name() { var args = new ExplicitArguments(); var theNode = new Node(); args.SetArg("node", theNode); - IConfiguredInstance instance = new ExplicitInstance(typeof (Command), args, null); + IConfiguredInstance instance = new ExplicitInstance(typeof (Command), args, new SmartInstance<Command>()); Assert.AreSame(theNode, instance.GetChild("node", typeof (Node), new StubBuildSession())); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fli...@us...> - 2008-12-19 15:46:43
|
Revision: 202 http://structuremap.svn.sourceforge.net/structuremap/?rev=202&view=rev Author: flimflan Date: 2008-12-19 15:46:37 +0000 (Fri, 19 Dec 2008) Log Message: ----------- Tagging 2.5 release Added Paths: ----------- tags/Release_2.5/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <fli...@us...> - 2008-12-19 15:18:03
|
Revision: 201 http://structuremap.svn.sourceforge.net/structuremap/?rev=201&view=rev Author: flimflan Date: 2008-12-19 15:17:56 +0000 (Fri, 19 Dec 2008) Log Message: ----------- Added missing DebuggerVisualizers test project Added Paths: ----------- trunk/Source/StructureMap.DebuggerVisualizers.Testing/ trunk/Source/StructureMap.DebuggerVisualizers.Testing/Program.cs trunk/Source/StructureMap.DebuggerVisualizers.Testing/Properties/ trunk/Source/StructureMap.DebuggerVisualizers.Testing/Properties/AssemblyInfo.cs trunk/Source/StructureMap.DebuggerVisualizers.Testing/SampleTypes.cs trunk/Source/StructureMap.DebuggerVisualizers.Testing/StructureMap.DebuggerVisualizers.Testing.csproj trunk/Source/StructureMap.DebuggerVisualizers.Testing/VisualizerTests.cs Property changes on: trunk/Source/StructureMap.DebuggerVisualizers.Testing ___________________________________________________________________ Added: svn:ignore + bin obj Added: trunk/Source/StructureMap.DebuggerVisualizers.Testing/Program.cs =================================================================== --- trunk/Source/StructureMap.DebuggerVisualizers.Testing/Program.cs (rev 0) +++ trunk/Source/StructureMap.DebuggerVisualizers.Testing/Program.cs 2008-12-19 15:17:56 UTC (rev 201) @@ -0,0 +1,32 @@ +using System.Diagnostics; +using System.Windows.Forms; + +namespace StructureMap.DebuggerVisualizers.Testing +{ + class Program + { + static void Main(string[] args) + { + var container = new Container( x => + { + x.Scan(s => + { + s.TheCallingAssembly(); + s.WithDefaultConventions(); + }); + x.ForRequestedType<IDoMore<string>>().TheDefaultIsConcreteType<DoForStrings>(); + x.ForRequestedType<IDoThat>().AddInstances(i => + { + i.OfConcreteType<DoThat>().WithName("Red"); + i.OfConcreteType<DoThat>().WithName("Blue"); + }); + }); + + ObjectFactory.Initialize(i => i.ForRequestedType<IDoThat>().TheDefaultIsConcreteType<DoThat>()); + Debug.WriteLine(container.WhatDoIHave()); + + var details = ContainerVisualizerObjectSource.BuildContainerDetails(container); + Application.Run(new ContainerForm(details)); + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap.DebuggerVisualizers.Testing/Properties/AssemblyInfo.cs =================================================================== --- trunk/Source/StructureMap.DebuggerVisualizers.Testing/Properties/AssemblyInfo.cs (rev 0) +++ trunk/Source/StructureMap.DebuggerVisualizers.Testing/Properties/AssemblyInfo.cs 2008-12-19 15:17:56 UTC (rev 201) @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("StructureMap.DebuggerVisualizers.Runner")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("StructureMap.DebuggerVisualizers.Runner")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d5786571-ba46-4985-a1a7-7360d8d3190e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] Added: trunk/Source/StructureMap.DebuggerVisualizers.Testing/SampleTypes.cs =================================================================== --- trunk/Source/StructureMap.DebuggerVisualizers.Testing/SampleTypes.cs (rev 0) +++ trunk/Source/StructureMap.DebuggerVisualizers.Testing/SampleTypes.cs 2008-12-19 15:17:56 UTC (rev 201) @@ -0,0 +1,63 @@ +namespace StructureMap.DebuggerVisualizers.Testing +{ + public interface IDoThis + { + void Do(); + } + + public interface IDoThat + { + void DoIt(); + } + + public interface IDoMore<T> + { + void DoDo(T thing); + } + + public interface IHasTwoGenerics<FIRST, SECOND> + { + SECOND DoIt(FIRST input); + } + + public class DoThis : IDoThis + { + public void Do() + { + + } + } + + public class DoThat : IDoThat + { + public void DoIt() + { + + } + } + + public class DoMore<T> :IDoMore<T> + { + public void DoDo(T thing) + { + + } + } + + public class HasTwoGenerics<FIRST, SECOND> : IHasTwoGenerics<FIRST, SECOND> + { + public SECOND DoIt(FIRST input) + { + throw new System.NotImplementedException(); + } + } + + public class DoForStrings :IDoMore<string> + { + public void DoDo(string thing) + { + + + } + } +} \ No newline at end of file Added: trunk/Source/StructureMap.DebuggerVisualizers.Testing/StructureMap.DebuggerVisualizers.Testing.csproj =================================================================== --- trunk/Source/StructureMap.DebuggerVisualizers.Testing/StructureMap.DebuggerVisualizers.Testing.csproj (rev 0) +++ trunk/Source/StructureMap.DebuggerVisualizers.Testing/StructureMap.DebuggerVisualizers.Testing.csproj 2008-12-19 15:17:56 UTC (rev 201) @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{13C368E6-A7BE-46E8-8CFB-64010C825748}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>StructureMap.DebuggerVisualizers.Testing</RootNamespace> + <AssemblyName>StructureMap.DebuggerVisualizers.Testing</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <StartupObject> + </StartupObject> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.VisualStudio.DebuggerVisualizers, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> + <Reference Include="nunit.framework, Version=2.4.0.2, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\bin\NUnit\nunit.framework.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Windows.Forms" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SampleTypes.cs" /> + <Compile Include="VisualizerTests.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\StructureMap.DebuggerVisualizers\StructureMap.DebuggerVisualizers.csproj"> + <Project>{F023DA4D-0B7D-4836-A56A-21F22A0A2D71}</Project> + <Name>StructureMap.DebuggerVisualizers</Name> + </ProjectReference> + <ProjectReference Include="..\StructureMap\StructureMap.csproj"> + <Project>{3F36EA80-2F9A-4DAD-BA27-5AC6163A2EE3}</Project> + <Name>StructureMap</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> \ No newline at end of file Added: trunk/Source/StructureMap.DebuggerVisualizers.Testing/VisualizerTests.cs =================================================================== --- trunk/Source/StructureMap.DebuggerVisualizers.Testing/VisualizerTests.cs (rev 0) +++ trunk/Source/StructureMap.DebuggerVisualizers.Testing/VisualizerTests.cs 2008-12-19 15:17:56 UTC (rev 201) @@ -0,0 +1,58 @@ +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; +using StructureMap.Pipeline; + +namespace StructureMap.DebuggerVisualizers.Testing +{ + [TestFixture] + public class VisualizerTests + { + [Test] + public void can_serialize_container_details() + { + var pluginTypeDetails = new[]{ new PluginTypeDetail(typeof(string), typeof(BuildPolicy), new[]{ new InstanceDetail("First", "First Instance", typeof(string)), }) }; + var wrapper = new ContainerDetail(new[]{"config"}, pluginTypeDetails); + var binaryFormatter = new BinaryFormatter(); + Stream stream = new MemoryStream(); + binaryFormatter.Serialize(stream, wrapper); + + stream.Position = 0; + var detailOnOtherSide = (ContainerDetail) binaryFormatter.Deserialize(stream); + Assert.That(detailOnOtherSide, Is.Not.Null); + Assert.That(detailOnOtherSide, Is.TypeOf(typeof(ContainerDetail))); + } + + [Test] + public void display_nongeneric_types() + { + Assert.That( typeof(IDoThat).AsCSharp(), Is.EqualTo("IDoThat")); + } + + [Test] + public void display_open_generics_using_c_sharp_syntax() + { + Assert.That(typeof (IHasTwoGenerics<,>).AsCSharp(), Is.EqualTo("IHasTwoGenerics<FIRST,SECOND>")); + } + + [Test] + public void display_closed_generics_using_c_sharp_syntax() + { + Assert.That(typeof(IHasTwoGenerics<string, int>).AsCSharp(), Is.EqualTo("IHasTwoGenerics<String,Int32>")); + } + + [Test] + public void display_open_generics_using_c_sharp_syntax_with_fullnames() + { + Assert.That(typeof(IHasTwoGenerics<,>).AsCSharp(t => t.FullName), Is.EqualTo("StructureMap.DebuggerVisualizers.Testing.IHasTwoGenerics<FIRST,SECOND>")); + } + + [Test] + public void display_closed_generics_using_c_sharp_syntax_with_fullnames() + { + Assert.That(typeof(IHasTwoGenerics<string, int>).AsCSharp(t => t.FullName), Is.EqualTo("StructureMap.DebuggerVisualizers.Testing.IHasTwoGenerics<System.String,System.Int32>")); + } + + } +} \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |