# HG changeset patch # User Steven Robbins # Date 1268391528 0 # Branch child.containers # Node ID 09548fdbae4fd8a3f99d94b4466fa5ce233e4ded # Parent fbfa37ec2d214b6095e5fb8109eb217f8cf1b033 Initial cut of child containers diff -r fbfa37ec2d214b6095e5fb8109eb217f8cf1b033 -r 09548fdbae4fd8a3f99d94b4466fa5ce233e4ded TinyIoC.Tests/TinyIoCTests.cs --- a/TinyIoC.Tests/TinyIoCTests.cs Fri Mar 12 08:16:46 2010 +0000 +++ b/TinyIoC.Tests/TinyIoCTests.cs Fri Mar 12 10:58:48 2010 +0000 @@ -1884,31 +1884,124 @@ [TestMethod] public void ChildContainerResolve_TypeRegisteredWithParent_ResolvesType() { - throw new NotImplementedException(); + var container = UtilityMethods.GetContainer(); + var child = container.GetChildContainer(); + container.Register(); + + var result = child.Resolve(); + + Assert.IsInstanceOfType(result, typeof(TestClassDefaultCtor)); } [TestMethod] public void ChildContainerCanResolve_TypeRegisteredWithParent_ReturnsTrue() { - throw new NotImplementedException(); + var container = UtilityMethods.GetContainer(); + var child = container.GetChildContainer(); + container.Register(); + + var result = child.CanResolve(); + + Assert.IsTrue(result); } [TestMethod] public void ChildContainerResolve_TypeRegisteredWithChild_ResolvesType() { - throw new NotImplementedException(); + var container = UtilityMethods.GetContainer(); + var child = container.GetChildContainer(); + child.Register(); + + var result = child.Resolve(); + + Assert.IsInstanceOfType(result, typeof(TestClassDefaultCtor)); } [TestMethod] public void ChildContainerCanResolve_TypeRegisteredWithChild_ReturnsTrue() { - throw new NotImplementedException(); + var container = UtilityMethods.GetContainer(); + var child = container.GetChildContainer(); + child.Register(); + + var result = child.CanResolve(); + + Assert.IsTrue(result); } [TestMethod] public void ChildContainerResolve_TypeRegisteredWithParentAndChild_ResolvesChildVersion() { - throw new NotImplementedException(); + var container = UtilityMethods.GetContainer(); + var containerInstance = new TestClassDefaultCtor(); + var child = container.GetChildContainer(); + var childInstance = new TestClassDefaultCtor(); + container.Register(containerInstance); + child.Register(childInstance); + + var result = child.Resolve(); + + Assert.ReferenceEquals(result, childInstance); } + + [TestMethod] + public void ChildContainerResolve_NamedOnlyRegisteredWithParent_ResolvesFromParent() + { + var container = UtilityMethods.GetContainer(); + var containerInstance = new TestClassDefaultCtor(); + var child = container.GetChildContainer(); + var childInstance = new TestClassDefaultCtor(); + container.Register(containerInstance, "Testing"); + child.Register(childInstance); + + var result = child.Resolve("Testing"); + + Assert.ReferenceEquals(result, containerInstance); + } + + [TestMethod] + public void ChildContainerCanResolve_NamedOnlyRegisteredWithParent_ReturnsTrue() + { + var container = UtilityMethods.GetContainer(); + var containerInstance = new TestClassDefaultCtor(); + var child = container.GetChildContainer(); + var childInstance = new TestClassDefaultCtor(); + container.Register(containerInstance, "Testing"); + child.Register(childInstance); + + var result = child.CanResolve("Testing"); + + Assert.IsTrue(result); + } + + [TestMethod] + public void ChildContainerResolve_NamedOnlyRegisteredWithParentUnnamedFallbackOn_ResolvesFromChild() + { + var container = UtilityMethods.GetContainer(); + var containerInstance = new TestClassDefaultCtor(); + var child = container.GetChildContainer(); + var childInstance = new TestClassDefaultCtor(); + container.Register(containerInstance, "Testing"); + child.Register(childInstance); + + var result = child.Resolve("Testing", new ResolveOptions() { NamedResolutionFailureAction = NamedResolutionFailureActions.AttemptUnnamedResolution }); + + Assert.ReferenceEquals(result, childInstance); + } + + [TestMethod] + public void ChildContainerResolve_NamedOnlyRegisteredWithParentChildNoRegistrationUnnamedFallbackOn_ResolvesFromParent() + { + var container = UtilityMethods.GetContainer(); + var containerInstance = new TestClassDefaultCtor(); + var child = container.GetChildContainer(); + var childInstance = new TestClassDefaultCtor(); + container.Register(containerInstance, "Testing"); + + var result = child.Resolve("Testing", new ResolveOptions() { NamedResolutionFailureAction = NamedResolutionFailureActions.AttemptUnnamedResolution }); + + Assert.ReferenceEquals(result, childInstance); + } + } } diff -r fbfa37ec2d214b6095e5fb8109eb217f8cf1b033 -r 09548fdbae4fd8a3f99d94b4466fa5ce233e4ded TinyIoC/TinyIoC.cs --- a/TinyIoC/TinyIoC.cs Fri Mar 12 08:16:46 2010 +0000 +++ b/TinyIoC/TinyIoC.cs Fri Mar 12 10:58:48 2010 +0000 @@ -87,6 +87,8 @@ item.Dispose(); } } + + GC.SuppressFinalize(this); } #endregion @@ -401,7 +403,7 @@ #region Child Containers public TinyIoCContainer GetChildContainer() { - throw new NotImplementedException(); + return new TinyIoCContainer(this); } #endregion @@ -1389,6 +1391,17 @@ RegisterDefaultTypes(); } + + ~TinyIoCContainer() + { + _RegisteredTypes.Clear(); + } + + TinyIoCContainer _Parent; + private TinyIoCContainer(TinyIoCContainer parent) : this() + { + this._Parent = parent; + } #endregion #region Internal Methods @@ -1517,8 +1530,9 @@ } // Fail if requesting named resolution and settings set to fail if unresolved + // Or bubble up if we have a parent if (!String.IsNullOrEmpty(name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.Fail) - return false; + return (_Parent != null) ? _Parent.CanResolveInternal(registration, parameters, options) : false; // Attemped unnamed fallback container resolution if relevant and requested if (!String.IsNullOrEmpty(name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.AttemptUnnamedResolution) @@ -1537,8 +1551,13 @@ return true; // Attempt unregistered construction if possible and requested + // If we cant', bubble if we have a parent if ((options.UnregisteredResolutionAction == UnregisteredResolutionActions.AttemptResolve) || (checkType.IsGenericType && options.UnregisteredResolutionAction == UnregisteredResolutionActions.GenericsOnly)) - return (GetBestConstructor(checkType, parameters, options) != null) ? true : false; + return (GetBestConstructor(checkType, parameters, options) != null) ? true : (_Parent != null) ? _Parent.CanResolveInternal(registration, parameters, options) : false; + + // Bubble resolution up the container tree if we have a parent + if (_Parent != null) + return _Parent.CanResolveInternal(registration, parameters, options); return false; } @@ -1584,7 +1603,13 @@ // Fail if requesting named resolution and settings set to fail if unresolved if (!String.IsNullOrEmpty(registration.Name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.Fail) - throw new TinyIoCResolutionException(registration.Type); + { + // Bubble resolution up the container tree if we have a parent + if (_Parent != null) + return _Parent.ResolveInternal(registration, parameters, options); + else + throw new TinyIoCResolutionException(registration.Type); + } // Attemped unnamed fallback container resolution if relevant and requested if (!String.IsNullOrEmpty(registration.Name) && options.NamedResolutionFailureAction == NamedResolutionFailureActions.AttemptUnnamedResolution) @@ -1613,6 +1638,10 @@ return ConstructType(registration.Type, parameters, options); } + // Bubble resolution up the container tree if we have a parent + if (_Parent != null) + return _Parent.ResolveInternal(registration, parameters, options); + // Unable to resolve - throw throw new TinyIoCResolutionException(registration.Type); } @@ -1779,7 +1808,7 @@ { property.SetValue(input, ResolveInternal(new TypeRegistration(property.PropertyType), NamedParameterOverloads.Default, resolveOptions), null); } - catch (Exception TinyIoCResolutionException) + catch (TinyIoCResolutionException) { // Catch any resolution errors and ignore them } @@ -1792,6 +1821,8 @@ public void Dispose() { _RegisteredTypes.Dispose(); + + GC.SuppressFinalize(this); } #endregion