|
From: <jer...@us...> - 2009-06-03 17:47:46
|
Revision: 248
http://structuremap.svn.sourceforge.net/structuremap/?rev=248&view=rev
Author: jeremydmiller
Date: 2009-06-03 17:47:44 +0000 (Wed, 03 Jun 2009)
Log Message:
-----------
got the dispose working for nested container
Modified Paths:
--------------
trunk/Source/StructureMap/Container.cs
trunk/Source/StructureMap/IContainer.cs
trunk/Source/StructureMap/PipelineGraph.cs
trunk/Source/StructureMap.Testing/Pipeline/NestedContainerSupportTester.cs
trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj
Added Paths:
-----------
trunk/Source/StructureMap.Testing/Pipeline/ContainerDisposalTester.cs
Modified: trunk/Source/StructureMap/Container.cs
===================================================================
--- trunk/Source/StructureMap/Container.cs 2009-06-03 16:21:03 UTC (rev 247)
+++ trunk/Source/StructureMap/Container.cs 2009-06-03 17:47:44 UTC (rev 248)
@@ -134,18 +134,8 @@
return getListOfTypeWithSession<T>(session);
}
- /// <summary>
- /// Injects the given object into a Container as the default for the designated
- /// PLUGINTYPE. Mostly used for temporarily setting up return values of the Container
- /// to introduce mocks or stubs during automated testing scenarios
- /// </summary>
- /// <typeparam name="PLUGINTYPE"></typeparam>
- /// <param name="instance"></param>
- public void Inject<PLUGINTYPE>(PLUGINTYPE instance)
- {
- _pipelineGraph.Inject(instance);
- }
+
/// <summary>
/// Creates or finds the default instance of type T
/// </summary>
@@ -162,20 +152,8 @@
return (T) FillDependencies(typeof (T));
}
- /// <summary>
- /// Injects the given object into a Container by name for the designated
- /// pluginType. Mostly used for temporarily setting up return values of the Container
- /// to introduce mocks or stubs during automated testing scenarios
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="name"></param>
- /// <param name="stub"></param>
- public void Inject<T>(string name, T stub)
- {
- LiteralInstance instance = new LiteralInstance(stub).WithName(name);
- _pipelineGraph.AddInstance<T>(instance);
- }
+
/// <summary>
/// Creates or resolves all registered instances of type T
/// </summary>
@@ -312,26 +290,8 @@
return GetInstance(type);
}
- /// <summary>
- /// Injects the given object into a Container as the default for the designated
- /// pluginType. Mostly used for temporarily setting up return values of the Container
- /// to introduce mocks or stubs during automated testing scenarios
- /// </summary>
- /// <param name="pluginType"></param>
- /// <param name="stub"></param>
- public void Inject(Type pluginType, object stub)
- {
- if (!CanBeCast(pluginType, stub.GetType()))
- {
- throw new StructureMapException(220, pluginType.FullName,
- stub.GetType().FullName);
- }
- var instance = new LiteralInstance(stub);
- _pipelineGraph.SetDefault(pluginType, instance);
- }
-
/// <summary>
/// Creates or resolves all registered instances of the pluginType
/// </summary>
@@ -470,7 +430,7 @@
/// <returns></returns>
public IContainer GetNestedContainer()
{
- return new Container()
+ return new Container
{
_interceptorLibrary = _interceptorLibrary,
_pipelineGraph = _pipelineGraph.Clone(),
@@ -485,12 +445,17 @@
/// <returns></returns>
public IContainer GetNestedContainer(string profileName)
{
- var container = GetNestedContainer();
+ IContainer container = GetNestedContainer();
container.SetDefaultsToProfile(profileName);
return container;
}
+ public void Dispose()
+ {
+ _transientCache.DisposeAndClear();
+ }
+
#endregion
private object buildInstanceWithArgs(Type pluginType, Instance defaultInstance, ExplicitArguments args,
@@ -552,16 +517,8 @@
return list;
}
- /// <summary>
- /// Sets the default instance for the PluginType
- /// </summary>
- /// <param name="pluginType"></param>
- /// <param name="instance"></param>
- public void Inject(Type pluginType, Instance instance)
- {
- _pipelineGraph.SetDefault(pluginType, instance);
- }
+
private BuildSession withNewSession(string name)
{
return new BuildSession(_pipelineGraph, _interceptorLibrary, _transientCache)
@@ -615,5 +572,65 @@
}
#endregion
+
+
+ /// <summary>
+ /// Injects the given object into a Container by name for the designated
+ /// pluginType. Mostly used for temporarily setting up return values of the Container
+ /// to introduce mocks or stubs during automated testing scenarios
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="name"></param>
+ /// <param name="object"></param>
+ public void Inject<T>(string name, T @object)
+ {
+ LiteralInstance instance = new LiteralInstance(@object).WithName(name);
+ _transientCache.Set(typeof(T), instance, @object);
+ _pipelineGraph.AddInstance<T>(instance);
+ }
+
+ /// <summary>
+ /// Sets the default instance for the PluginType
+ /// </summary>
+ /// <param name="pluginType"></param>
+ /// <param name="instance"></param>
+ public void Inject(Type pluginType, Instance instance)
+ {
+ _pipelineGraph.SetDefault(pluginType, instance);
+ }
+
+ /// <summary>
+ /// Injects the given object into a Container as the default for the designated
+ /// pluginType. Mostly used for temporarily setting up return values of the Container
+ /// to introduce mocks or stubs during automated testing scenarios
+ /// </summary>
+ /// <param name="pluginType"></param>
+ /// <param name="object"></param>
+ public void Inject(Type pluginType, object @object)
+ {
+ if (!CanBeCast(pluginType, @object.GetType()))
+ {
+ throw new StructureMapException(220, pluginType.FullName,
+ @object.GetType().FullName);
+ }
+
+
+ var instance = new LiteralInstance(@object);
+ _transientCache.Set(pluginType, instance, @object);
+ _pipelineGraph.SetDefault(pluginType, instance);
+ }
+
+ /// <summary>
+ /// Injects the given object into a Container as the default for the designated
+ /// PLUGINTYPE. Mostly used for temporarily setting up return values of the Container
+ /// to introduce mocks or stubs during automated testing scenarios
+ /// </summary>
+ /// <typeparam name="PLUGINTYPE"></typeparam>
+ /// <param name="object"></param>
+ public void Inject<PLUGINTYPE>(PLUGINTYPE @object)
+ {
+ var instance = _pipelineGraph.Inject(@object);
+ _transientCache.Set(typeof(PLUGINTYPE), instance, @object);
+ }
}
}
\ No newline at end of file
Modified: trunk/Source/StructureMap/IContainer.cs
===================================================================
--- trunk/Source/StructureMap/IContainer.cs 2009-06-03 16:21:03 UTC (rev 247)
+++ trunk/Source/StructureMap/IContainer.cs 2009-06-03 17:47:44 UTC (rev 248)
@@ -9,7 +9,7 @@
/// <summary>
/// The main "container" object that implements the Service Locator pattern
/// </summary>
- public interface IContainer
+ public interface IContainer : IDisposable
{
/// <summary>
/// Provides queryable access to the configured PluginType's and Instances of this Container
@@ -132,8 +132,8 @@
/// to introduce mocks or stubs during automated testing scenarios
/// </summary>
/// <param name="pluginType"></param>
- /// <param name="stub"></param>
- void Inject(Type pluginType, object stub);
+ /// <param name="object"></param>
+ void Inject(Type pluginType, object @object);
/// <summary>
/// Injects the given object into a Container by name for the designated
Modified: trunk/Source/StructureMap/PipelineGraph.cs
===================================================================
--- trunk/Source/StructureMap/PipelineGraph.cs 2009-06-03 16:21:03 UTC (rev 247)
+++ trunk/Source/StructureMap/PipelineGraph.cs 2009-06-03 17:47:44 UTC (rev 248)
@@ -179,11 +179,13 @@
ForType(typeof (T)).AddInstance(instance);
}
- public void Inject<PLUGINTYPE>(PLUGINTYPE instance)
+ public Instance Inject<PLUGINTYPE>(PLUGINTYPE instance)
{
var literalInstance = new LiteralInstance(instance);
ForType(typeof (PLUGINTYPE)).AddInstance(literalInstance);
SetDefault(typeof (PLUGINTYPE), literalInstance);
+
+ return literalInstance;
}
public void EjectAllInstancesOf<T>()
Added: trunk/Source/StructureMap.Testing/Pipeline/ContainerDisposalTester.cs
===================================================================
--- trunk/Source/StructureMap.Testing/Pipeline/ContainerDisposalTester.cs (rev 0)
+++ trunk/Source/StructureMap.Testing/Pipeline/ContainerDisposalTester.cs 2009-06-03 17:47:44 UTC (rev 248)
@@ -0,0 +1,151 @@
+using System;
+using NUnit.Framework;
+using StructureMap.Configuration.DSL;
+
+namespace StructureMap.Testing.Pipeline
+{
+ [TestFixture]
+ public class ContainerDisposalTester
+ {
+ [SetUp]
+ public void SetUp()
+ {
+ }
+
+ [Test]
+ public void disposing_a_nested_container_should_dispose_all_of_the_transient_objects_created_by_the_nested_container()
+ {
+ var container = new Container(x =>
+ {
+ x.For<I1>().Use<C1Yes>();
+ x.For<I2>().Use<C2Yes>();
+ x.For<I3>().AddInstances(o =>
+ {
+ o.OfConcreteType<C3Yes>().WithName("1");
+ o.OfConcreteType<C3Yes>().WithName("2");
+ });
+ });
+
+ var child = container.GetNestedContainer();
+
+ var disposables = new Disposable[]
+ {
+ child.GetInstance<I1>().ShouldBeOfType<Disposable>(),
+ child.GetInstance<I2>().ShouldBeOfType<Disposable>(),
+ child.GetInstance<I3>("1").ShouldBeOfType<Disposable>(),
+ child.GetInstance<I3>("2").ShouldBeOfType<Disposable>(),
+ };
+
+ child.Dispose();
+
+ foreach (var disposable in disposables)
+ {
+ disposable.WasDisposed.ShouldBeTrue();
+ }
+ }
+
+ [Test]
+ public void disposing_a_nested_container_does_not_try_to_dispose_objects_created_by_the_parent()
+ {
+ var container = new Container(x =>
+ {
+ x.ForSingletonOf<I1>().Use<C1No>();
+ });
+
+ var child = container.GetNestedContainer();
+
+ // Blows up if the Dispose() is called
+ var notDisposable = child.GetInstance<I1>();
+
+ child.Dispose();
+ }
+
+ [Test]
+ public void should_dispose_objects_injected_into_the_container_1()
+ {
+ var container = new Container().GetNestedContainer();
+
+ var disposable = new C1Yes();
+ container.Inject<I1>(disposable);
+
+ container.GetInstance<I1>().ShouldBeTheSameAs(disposable);
+
+ container.Dispose();
+
+ disposable.WasDisposed.ShouldBeTrue();
+ }
+
+ [Test]
+ public void should_dispose_objects_injected_into_the_container_2()
+ {
+ var container = new Container().GetNestedContainer();
+
+ var disposable = new C1Yes();
+ container.Inject<I1>(disposable);
+
+ container.Dispose();
+
+ disposable.WasDisposed.ShouldBeTrue();
+ }
+
+ [Test]
+ public void should_dispose_objects_injected_into_the_container_3()
+ {
+ var container = new Container().GetNestedContainer();
+
+ var disposable = new C1Yes();
+ container.Inject<I1>("blue", disposable);
+
+ container.Dispose();
+
+ disposable.WasDisposed.ShouldBeTrue();
+ }
+
+
+ [Test]
+ public void should_dispose_objects_injected_into_the_container_4()
+ {
+ var container = new Container().GetNestedContainer();
+
+ var disposable = new C1Yes();
+ container.Inject(typeof(I1), disposable);
+
+ container.Dispose();
+
+ disposable.WasDisposed.ShouldBeTrue();
+ }
+ }
+
+ public class Disposable : IDisposable
+ {
+ private bool _wasDisposed;
+
+ public void Dispose()
+ {
+ if (_wasDisposed) Assert.Fail("This object should not be disposed twice");
+
+ _wasDisposed = true;
+ }
+
+ public bool WasDisposed { get { return _wasDisposed; } }
+ }
+
+ public class NotDisposable : IDisposable
+ {
+ public void Dispose()
+ {
+ Assert.Fail("This object should not be disposed");
+ }
+ }
+
+ public interface I1{}
+ public interface I2{}
+ public interface I3{}
+
+ public class C1Yes : Disposable, I1{}
+ public class C1No : NotDisposable, I1{}
+ public class C2Yes : Disposable, I2{}
+ public class C2No : Disposable, I2{}
+ public class C3Yes : Disposable, I3{}
+ public class C3No : Disposable, I3{}
+}
\ No newline at end of file
Modified: trunk/Source/StructureMap.Testing/Pipeline/NestedContainerSupportTester.cs
===================================================================
--- trunk/Source/StructureMap.Testing/Pipeline/NestedContainerSupportTester.cs 2009-06-03 16:21:03 UTC (rev 247)
+++ trunk/Source/StructureMap.Testing/Pipeline/NestedContainerSupportTester.cs 2009-06-03 17:47:44 UTC (rev 248)
@@ -14,6 +14,7 @@
{
}
+
[Test]
public void transient_service_in_the_parent_container_is_effectively_a_singleton_for_the_nested_container()
{
@@ -36,6 +37,29 @@
}
[Test]
+ public void inject_into_the_child_does_not_affect_the_parent_container()
+ {
+ var parent = new Container(x =>
+ {
+ x.For<IWidget>().Use<AWidget>();
+ });
+
+ var child = parent.GetNestedContainer();
+ var childWidget = new ColorWidget("blue");
+ child.Inject<IWidget>(childWidget);
+
+ // do the check repeatedly
+ child.GetInstance<IWidget>().ShouldBeTheSameAs(childWidget);
+ child.GetInstance<IWidget>().ShouldBeTheSameAs(childWidget);
+ child.GetInstance<IWidget>().ShouldBeTheSameAs(childWidget);
+
+
+ // now, compare to the parent
+ parent.GetInstance<IWidget>().ShouldNotBeTheSameAs(childWidget);
+
+ }
+
+ [Test]
public void singleton_service_in_the_parent_is_found_by_the_child()
{
var parent = new Container(x =>
Modified: trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj
===================================================================
--- trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-06-03 16:21:03 UTC (rev 247)
+++ trunk/Source/StructureMap.Testing/StructureMap.Testing.csproj 2009-06-03 17:47:44 UTC (rev 248)
@@ -346,6 +346,7 @@
<Compile Include="Pipeline\ConditionalInstanceTester.cs" />
<Compile Include="Pipeline\ConfiguredInstanceTester.cs" />
<Compile Include="Pipeline\ConstructorInstanceTester.cs" />
+ <Compile Include="Pipeline\ContainerDisposalTester.cs" />
<Compile Include="Pipeline\ContainerIsInTheContainerTester.cs" />
<Compile Include="Pipeline\DefaultInstanceTester.cs" />
<Compile Include="Pipeline\GenericsHelperExpressionTester.cs" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|