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