|
From: <jer...@us...> - 2009-04-19 18:40:59
|
Revision: 235
http://structuremap.svn.sourceforge.net/structuremap/?rev=235&view=rev
Author: jeremydmiller
Date: 2009-04-19 18:40:49 +0000 (Sun, 19 Apr 2009)
Log Message:
-----------
Making StructureMap throw a clean error when a cyclic dependency is detected
Modified Paths:
--------------
trunk/Source/StructureMap/BuildSession.cs
trunk/Source/StructureMap/CloseGenericTypeExpression.cs
trunk/Source/StructureMap/Container.cs
trunk/Source/StructureMap/IInstanceFactory.cs
trunk/Source/StructureMap/InstanceCache.cs
trunk/Source/StructureMap/InstanceFactory.cs
trunk/Source/StructureMap/Pipeline/BuildFrame.cs
trunk/Source/StructureMap/Pipeline/BuildStack.cs
trunk/Source/StructureMap/Pipeline/Instance.cs
trunk/Source/StructureMap/StructureMap.csproj
trunk/Source/StructureMap/StructureMapException.resx
trunk/Source/StructureMap/TypeExtensions.cs
trunk/Source/StructureMap.Testing/Pipeline/BuildStackTester.cs
trunk/Source/StructureMap.Testing/Pipeline/GenericsHelperExpressionTester.cs
trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj
Added Paths:
-----------
trunk/Source/StructureMap/IContext.cs
trunk/Source/StructureMap.Testing/BidirectionalDependencies.cs
Modified: trunk/Source/StructureMap/BuildSession.cs
===================================================================
--- trunk/Source/StructureMap/BuildSession.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/BuildSession.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -1,5 +1,4 @@
using System;
-using System.Collections;
using StructureMap.Graph;
using StructureMap.Interceptors;
using StructureMap.Pipeline;
@@ -7,68 +6,6 @@
namespace StructureMap
{
- public interface IContext
- {
- /// <summary>
- /// Gets a reference to the <see cref="BuildStack">BuildStack</see> for this build session
- /// </summary>
- BuildStack BuildStack { get; }
-
- /// <summary>
- /// The concrete type of the immediate parent object in the object graph
- /// </summary>
- Type ParentType { get; }
-
- /// <summary>
- /// Get the object of type T that is valid for this build session.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <returns></returns>
- 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; }
-
- /// <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);
-
- /// <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
{
private readonly BuildStack _buildStack = new BuildStack();
@@ -102,13 +39,12 @@
{
}
- public BuildSession() : this(new PluginGraph())
+ public BuildSession()
+ : this(new PluginGraph())
{
}
- public string RequestedName { get; set; }
-
protected PipelineGraph pipelineGraph
{
get { return _pipelineGraph; }
@@ -116,6 +52,12 @@
#region IContext Members
+ public string RequestedName
+ {
+ get;
+ set;
+ }
+
public BuildStack BuildStack
{
get { return _buildStack; }
@@ -145,6 +87,28 @@
get { return _buildStack.Root; }
}
+ public virtual void RegisterDefault(Type pluginType, object defaultObject)
+ {
+ RegisterDefault(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;
+ }
+
#endregion
public virtual object CreateInstance(Type pluginType, string name)
@@ -158,6 +122,7 @@
return CreateInstance(pluginType, instance);
}
+ // This is where all Creation happens
public virtual object CreateInstance(Type pluginType, Instance instance)
{
object result = _cache.Get(pluginType, instance);
@@ -175,27 +140,17 @@
public virtual Array CreateInstanceArray(Type pluginType, Instance[] instances)
{
- Array array;
-
if (instances == null)
{
- IList list = forType(pluginType).GetAllInstances(this);
- array = Array.CreateInstance(pluginType, list.Count);
- for (int i = 0; i < list.Count; i++)
- {
- array.SetValue(list[i], i);
- }
+ instances = forType(pluginType).AllInstances;
}
- else
- {
- array = Array.CreateInstance(pluginType, instances.Length);
- for (int i = 0; i < instances.Length; i++)
- {
- Instance instance = instances[i];
- object arrayValue = forType(pluginType).Build(this, instance);
- array.SetValue(arrayValue, i);
- }
+ Array array = Array.CreateInstance(pluginType, instances.Length);
+ for (int i = 0; i < instances.Length; i++)
+ {
+ Instance instance = instances[i];
+ object arrayValue = CreateInstance(pluginType, instance);
+ array.SetValue(arrayValue, i);
}
return array;
@@ -212,37 +167,15 @@
return _interceptorLibrary.FindInterceptor(actualValue.GetType()).Process(actualValue, this);
}
- public virtual void RegisterDefault(Type pluginType, object defaultObject)
- {
- RegisterDefault(pluginType, () => defaultObject);
- }
-
public virtual void RegisterDefault(Type pluginType, Func<object> creator)
{
_defaults[pluginType] = creator;
}
- 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);
}
}
-}
+}
\ No newline at end of file
Modified: trunk/Source/StructureMap/CloseGenericTypeExpression.cs
===================================================================
--- trunk/Source/StructureMap/CloseGenericTypeExpression.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/CloseGenericTypeExpression.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -1,4 +1,6 @@
using System;
+using System.Collections;
+using System.Collections.Generic;
namespace StructureMap
{
@@ -7,8 +9,13 @@
T As<T>();
}
- public class CloseGenericTypeExpression : OpenGenericTypeSpecificationExpression
+ public interface OpenGenericTypeListSpecificationExpression
{
+ IList<T> As<T>();
+ }
+
+ public class CloseGenericTypeExpression : OpenGenericTypeSpecificationExpression, OpenGenericTypeListSpecificationExpression
+ {
private readonly object _subject;
private readonly IContainer _container;
private Type _pluginType;
@@ -26,13 +33,18 @@
/// <returns></returns>
public OpenGenericTypeSpecificationExpression GetClosedTypeOf(Type type)
{
+ closeType(type);
+ return this;
+ }
+
+ private void closeType(Type type)
+ {
if (!type.IsGeneric())
{
throw new StructureMapException(285);
}
_pluginType = type.MakeGenericType(_subject.GetType());
- return this;
}
/// <summary>
@@ -44,5 +56,23 @@
{
return (T) _container.With(_subject.GetType(), _subject).GetInstance(_pluginType);
}
+
+ public OpenGenericTypeListSpecificationExpression GetAllClosedTypesOf(Type type)
+ {
+ closeType(type);
+ return this;
+ }
+
+ IList<T> OpenGenericTypeListSpecificationExpression.As<T>()
+ {
+ IList list = _container.With(_subject.GetType(), _subject).GetAllInstances(_pluginType);
+ var returnValue = new List<T>();
+ foreach (var o in list)
+ {
+ returnValue.Add((T) o);
+ }
+
+ return returnValue;
+ }
}
}
\ No newline at end of file
Modified: trunk/Source/StructureMap/Container.cs
===================================================================
--- trunk/Source/StructureMap/Container.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/Container.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -11,7 +11,6 @@
namespace StructureMap
{
-
public class Container : TypeRules, IContainer
{
private InterceptorLibrary _interceptorLibrary;
@@ -147,7 +146,8 @@
args.RegisterDefaults(session);
- return forType(type).GetAllInstances(session);
+ var instances = session.CreateInstanceArray(type, null);
+ return new ArrayList(instances);
}
@@ -365,7 +365,8 @@
/// <returns></returns>
public IList GetAllInstances(Type pluginType)
{
- return forType(pluginType).GetAllInstances(withNewSession(Plugin.DEFAULT));
+ var instances = withNewSession(Plugin.DEFAULT).CreateInstanceArray(pluginType, null);
+ return new ArrayList(instances);
}
/// <summary>
@@ -482,7 +483,7 @@
private IList<T> getListOfTypeWithSession<T>(BuildSession session)
{
var list = new List<T>();
- foreach (T instance in forType(typeof (T)).GetAllInstances(session))
+ foreach (T instance in session.CreateInstanceArray(typeof(T), null))
{
list.Add(instance);
}
@@ -505,12 +506,6 @@
return new BuildSession(_pipelineGraph, _interceptorLibrary){RequestedName = name};
}
-
- protected IInstanceFactory forType(Type type)
- {
- return _pipelineGraph.ForType(type);
- }
-
/// <summary>
/// Convenience method to request an object using an Open Generic
/// Type and its parameter Types
Added: trunk/Source/StructureMap/IContext.cs
===================================================================
--- trunk/Source/StructureMap/IContext.cs (rev 0)
+++ trunk/Source/StructureMap/IContext.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -0,0 +1,67 @@
+using System;
+using StructureMap.Pipeline;
+
+namespace StructureMap
+{
+ public interface IContext
+ {
+ /// <summary>
+ /// Gets a reference to the <see cref="BuildStack">BuildStack</see> for this build session
+ /// </summary>
+ BuildStack BuildStack { get; }
+
+ /// <summary>
+ /// The concrete type of the immediate parent object in the object graph
+ /// </summary>
+ Type ParentType { get; }
+
+ /// <summary>
+ /// Get the object of type T that is valid for this build session.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns></returns>
+ 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; }
+
+ /// <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);
+
+ /// <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;
+ }
+}
\ No newline at end of file
Modified: trunk/Source/StructureMap/IInstanceFactory.cs
===================================================================
--- trunk/Source/StructureMap/IInstanceFactory.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/IInstanceFactory.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -16,15 +16,23 @@
IBuildPolicy Policy { get; }
Instance MissingInstance { get; set; }
+ Instance[] AllInstances
+ {
+ get;
+ }
+
void AddInstance(Instance instance);
Instance AddType<T>();
+ [Obsolete("Return the list of Instances instead")]
IList GetAllInstances(BuildSession session);
+
object Build(BuildSession session, Instance instance);
Instance FindInstance(string name);
- void ForEachInstance(Action<Instance> action);
void ImportFrom(PluginFamily family);
void EjectAllInstances();
+
+
}
}
\ No newline at end of file
Modified: trunk/Source/StructureMap/InstanceCache.cs
===================================================================
--- trunk/Source/StructureMap/InstanceCache.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/InstanceCache.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -39,6 +39,14 @@
public void Set(Type pluginType, Instance Instance, object result)
{
Dictionary<Instance, object> cache = getCache(pluginType);
+
+ if (cache.ContainsKey(Instance))
+ {
+ string message = string.Format("Duplicate Objects detected for Instance {0} of Type {1}", Instance.Name,
+ pluginType.AssemblyQualifiedName);
+ throw new ApplicationException(message);
+
+ }
cache.Add(Instance, result);
}
}
Modified: trunk/Source/StructureMap/InstanceFactory.cs
===================================================================
--- trunk/Source/StructureMap/InstanceFactory.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/InstanceFactory.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -87,16 +87,20 @@
get { return _instances.GetAll(); }
}
+ public Instance[] AllInstances
+ {
+ get
+ {
+ return _instances.GetAll();
+ }
+ }
+
public IBuildPolicy Policy
{
get { return _policy; }
set { _policy = value; }
}
- public void ForEachInstance(Action<Instance> action)
- {
- _instances.Each(action);
- }
public void AddInstance(Instance instance)
{
Modified: trunk/Source/StructureMap/Pipeline/BuildFrame.cs
===================================================================
--- trunk/Source/StructureMap/Pipeline/BuildFrame.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/Pipeline/BuildFrame.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -115,5 +115,30 @@
return result;
}
}
+
+ public bool Contains(BuildFrame frame)
+ {
+ if (_requestedType == frame._requestedType && _name == frame._name)
+ {
+ return true;
+ }
+
+ return _next == null ? false : _next.Contains(frame);
+ }
+
+ public string ToStackString()
+ {
+ string message = "\n1.) " + ToString();
+ var next = _next;
+
+ int i = 2;
+ while (next != null)
+ {
+ message += "\n{0}.) {1}".ToFormat(i++, next);
+ next = next._next;
+ }
+
+ return message;
+ }
}
}
\ No newline at end of file
Modified: trunk/Source/StructureMap/Pipeline/BuildStack.cs
===================================================================
--- trunk/Source/StructureMap/Pipeline/BuildStack.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/Pipeline/BuildStack.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -1,3 +1,5 @@
+using System;
+
namespace StructureMap.Pipeline
{
/// <summary>
@@ -45,6 +47,13 @@
}
else
{
+ if (_root.Contains(frame))
+ {
+
+
+ throw new StructureMapException(295, frame.ToString(), _root.ToStackString());
+ }
+
_current.Attach(frame);
_current = frame;
}
Modified: trunk/Source/StructureMap/Pipeline/Instance.cs
===================================================================
--- trunk/Source/StructureMap/Pipeline/Instance.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/Pipeline/Instance.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
using StructureMap.Diagnostics;
using StructureMap.Graph;
using StructureMap.Interceptors;
@@ -124,7 +125,8 @@
{
if (!doesRecordOnTheStack) return;
- session.BuildStack.Push(new BuildFrame(pluginType, Name, getConcreteType(pluginType)));
+ var frame = new BuildFrame(pluginType, Name, getConcreteType(pluginType));
+ session.BuildStack.Push(frame);
}
private object createRawObject(Type pluginType, BuildSession session)
Modified: trunk/Source/StructureMap/StructureMap.csproj
===================================================================
--- trunk/Source/StructureMap/StructureMap.csproj 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/StructureMap.csproj 2009-04-19 18:40:49 UTC (rev 235)
@@ -405,6 +405,7 @@
<Compile Include="Graph\ITypeScanner.cs" />
<Compile Include="Graph\PluggableAttributeScanner.cs" />
<Compile Include="Graph\PluginCache.cs" />
+ <Compile Include="IContext.cs" />
<Compile Include="Pipeline\ConditionalInstance.cs" />
<Compile Include="Pipeline\HttpSessionBuildPolicy.cs" />
<Compile Include="Pipeline\SessionWrapper.cs" />
Modified: trunk/Source/StructureMap/StructureMapException.resx
===================================================================
--- trunk/Source/StructureMap/StructureMapException.resx 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/StructureMapException.resx 2009-04-19 18:40:49 UTC (rev 235)
@@ -271,4 +271,7 @@
<data name="290" xml:space="preserve">
<value>Could not load the designated Registry class '{0}'</value>
</data>
+ <data name="295" xml:space="preserve">
+ <value>Bidirectional Dependency Problem detected with {0}. The BuildStack is: {1}</value>
+ </data>
</root>
\ No newline at end of file
Modified: trunk/Source/StructureMap/TypeExtensions.cs
===================================================================
--- trunk/Source/StructureMap/TypeExtensions.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap/TypeExtensions.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -72,6 +72,16 @@
return pluggedType.BaseType == typeof(object) ? null : pluggedType.BaseType.FindInterfaceThatCloses(templateType);
}
+ public static bool IsNullable(this Type type)
+ {
+ return type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>);
+ }
+
+ public static Type GetInnerTypeFromNullable(this Type nullableType)
+ {
+ return nullableType.GetGenericArguments()[0];
+ }
+
public static string GetName(this Type type)
{
if (type.IsGenericType)
Added: trunk/Source/StructureMap.Testing/BidirectionalDependencies.cs
===================================================================
--- trunk/Source/StructureMap.Testing/BidirectionalDependencies.cs (rev 0)
+++ trunk/Source/StructureMap.Testing/BidirectionalDependencies.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -0,0 +1,68 @@
+using System;
+using System.Diagnostics;
+using NUnit.Framework;
+
+namespace StructureMap.Testing
+{
+ [TestFixture] public class BidirectionalDependencies
+ {
+ private Container container;
+
+ [SetUp] public void SetUp()
+ {
+ container = new Container(x =>
+ {
+ x.ForRequestedType<IBiView>().TheDefaultIsConcreteType<BiView>();
+ x.ForRequestedType<IBiPresenter>().TheDefaultIsConcreteType<BiPresenter>();
+ });
+ }
+
+ [Test] public void do_not_blow_up_with_a_stack_overflow_problem()
+ {
+ try
+ {
+ container.GetInstance<BiView>();
+ Assert.Fail("Should have thrown error");
+ }
+ catch (StructureMapException e)
+ {
+ Debug.WriteLine(e.ToString());
+ e.ErrorCode.ShouldEqual(295);
+ }
+ }
+ }
+
+
+ public interface IBiView{}
+ public interface IBiPresenter{}
+
+ public class BiView : IBiView
+ {
+ private readonly IBiPresenter _presenter;
+
+ public BiView(IBiPresenter presenter)
+ {
+ _presenter = presenter;
+ }
+
+ public IBiPresenter Presenter
+ {
+ get { return _presenter; }
+ }
+ }
+
+ public class BiPresenter : IBiPresenter
+ {
+ private readonly IBiView _view;
+
+ public BiPresenter(IBiView view)
+ {
+ _view = view;
+ }
+
+ public IBiView View
+ {
+ get { return _view; }
+ }
+ }
+}
\ No newline at end of file
Modified: trunk/Source/StructureMap.Testing/Pipeline/BuildStackTester.cs
===================================================================
--- trunk/Source/StructureMap.Testing/Pipeline/BuildStackTester.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap.Testing/Pipeline/BuildStackTester.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -43,4 +43,26 @@
stack.Current.ShouldBeTheSameAs(root);
}
}
+
+ [TestFixture] public class when_using_build_frame_contains
+ {
+ [SetUp] public void SetUp()
+ {
+
+ }
+
+ [Test] public void true_if_matching()
+ {
+ var frame1 = new BuildFrame(typeof (IWidget), "red", typeof (ColorWidget));
+ var frame2 = new BuildFrame(typeof (IWidget), "red", typeof (ColorWidget));
+ var frame3 = new BuildFrame(typeof (IWidget), "green", typeof (ColorWidget));
+
+ frame1.Contains(frame2).ShouldBeTrue();
+ frame1.Contains(frame3).ShouldBeFalse();
+
+ frame3.Attach(frame2);
+
+ frame3.Contains(frame1).ShouldBeTrue();
+ }
+ }
}
\ No newline at end of file
Modified: trunk/Source/StructureMap.Testing/Pipeline/GenericsHelperExpressionTester.cs
===================================================================
--- trunk/Source/StructureMap.Testing/Pipeline/GenericsHelperExpressionTester.cs 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap.Testing/Pipeline/GenericsHelperExpressionTester.cs 2009-04-19 18:40:49 UTC (rev 235)
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using NUnit.Framework;
namespace StructureMap.Testing.Pipeline
@@ -182,6 +183,30 @@
}
}
+ [TestFixture]
+ public class when_getting_all_closed_type_from_an_open_generic_type_by_providing_an_input_parameter
+ {
+ [Test]
+ public void fetch_the_objects()
+ {
+ var container = new Container(x =>
+ {
+ x.ForRequestedType<IHandler<Shipment>>().TheDefaultIsConcreteType<ShipmentHandler>();
+ x.ForRequestedType<IHandler<Shipment>>().AddConcreteType<ShipmentHandler2>();
+ });
+
+ var shipment = new Shipment();
+
+ IList<IHandler> handlers = container
+ .ForObject(shipment)
+ .GetAllClosedTypesOf(typeof(IHandler<>))
+ .As<IHandler>();
+
+ handlers[0].ShouldBeOfType<ShipmentHandler>();
+ handlers[1].ShouldBeOfType<ShipmentHandler2>();
+ }
+ }
+
public class Shipment
{
@@ -211,4 +236,19 @@
get { return _shipment; }
}
}
+
+ public class ShipmentHandler2 : IHandler<Shipment>
+ {
+ private readonly Shipment _shipment;
+
+ public ShipmentHandler2(Shipment shipment)
+ {
+ _shipment = shipment;
+ }
+
+ public Shipment Shipment
+ {
+ get { return _shipment; }
+ }
+ }
}
\ No newline at end of file
Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj
===================================================================
--- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-02-24 03:18:29 UTC (rev 234)
+++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-04-19 18:40:49 UTC (rev 235)
@@ -177,6 +177,7 @@
<Compile Include="AutoMocking\RhinoAutoMockerTester.cs" />
<Compile Include="AutoMocking\RhinoMockRepositoryProxyTester.cs" />
<Compile Include="AutoWiringExamples.cs" />
+ <Compile Include="BidirectionalDependencies.cs" />
<Compile Include="Bugs\BuildUpBug.cs" />
<Compile Include="Bugs\HttpSessionNullRefBug.cs" />
<Compile Include="Bugs\IDictionaryAndXmlBugTester.cs" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|