# HG changeset patch # User Steven Robbins # Date 1268415593 0 # Branch messenger # Node ID 4b22d23e7e3a47cc32cb6126e5149debf0157e95 # Parent cc7f9799c564076e4160ab974c6a84ecc205391e # Parent 09548fdbae4fd8a3f99d94b4466fa5ce233e4ded Merged in child containers branch diff -r cc7f9799c564076e4160ab974c6a84ecc205391e -r 4b22d23e7e3a47cc32cb6126e5149debf0157e95 TinyIoC.Tests/TinyIoCTests.cs --- a/TinyIoC.Tests/TinyIoCTests.cs Fri Mar 12 17:31:57 2010 +0000 +++ b/TinyIoC.Tests/TinyIoCTests.cs Fri Mar 12 17:39:53 2010 +0000 @@ -1861,5 +1861,147 @@ Assert.IsInstanceOfType(result2, typeof(ExternalTypes.IExternalTestInterface)); } + [TestMethod] + public void GetChildContainer_NoParameters_ReturnsContainerInstance() + { + var container = UtilityMethods.GetContainer(); + + var child = container.GetChildContainer(); + + Assert.IsInstanceOfType(child, typeof(TinyIoCContainer)); + } + + [TestMethod] + public void GetChildContainer_NoParameters_ContainerReturnedIsNewContainer() + { + var container = UtilityMethods.GetContainer(); + + var child = container.GetChildContainer(); + + Assert.IsFalse(object.ReferenceEquals(child, container)); + } + + [TestMethod] + public void ChildContainerResolve_TypeRegisteredWithParent_ResolvesType() + { + 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() + { + var container = UtilityMethods.GetContainer(); + var child = container.GetChildContainer(); + container.Register(); + + var result = child.CanResolve(); + + Assert.IsTrue(result); + } + + [TestMethod] + public void ChildContainerResolve_TypeRegisteredWithChild_ResolvesType() + { + 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() + { + var container = UtilityMethods.GetContainer(); + var child = container.GetChildContainer(); + child.Register(); + + var result = child.CanResolve(); + + Assert.IsTrue(result); + } + + [TestMethod] + public void ChildContainerResolve_TypeRegisteredWithParentAndChild_ResolvesChildVersion() + { + 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 cc7f9799c564076e4160ab974c6a84ecc205391e -r 4b22d23e7e3a47cc32cb6126e5149debf0157e95 TinyIoC/TinyIoC.cs --- a/TinyIoC/TinyIoC.cs Fri Mar 12 17:31:57 2010 +0000 +++ b/TinyIoC/TinyIoC.cs Fri Mar 12 17:39:53 2010 +0000 @@ -13,6 +13,9 @@ // FITNESS FOR A PARTICULAR PURPOSE. //=============================================================================== +// Comment this line if you don't want the TinyMessenger messenger/event aggregator +#define TINYMESSENGER + using System; using System.Collections.Generic; using System.Linq; @@ -87,6 +90,8 @@ item.Dispose(); } } + + GC.SuppressFinalize(this); } #endregion @@ -398,6 +403,13 @@ #endregion #region Public API + #region Child Containers + public TinyIoCContainer GetChildContainer() + { + return new TinyIoCContainer(this); + } + #endregion + #region Registration /// /// Attempt to automatically register all non-generic classes and interfaces in the current app domain. @@ -1382,6 +1394,17 @@ RegisterDefaultTypes(); } + + ~TinyIoCContainer() + { + _RegisteredTypes.Clear(); + } + + TinyIoCContainer _Parent; + private TinyIoCContainer(TinyIoCContainer parent) : this() + { + this._Parent = parent; + } #endregion #region Internal Methods @@ -1449,6 +1472,12 @@ private void RegisterDefaultTypes() { this.Register(this); + +#if TINYMESSENGER + // Only register the TinyMessenger singleton if we are the root container + if (this._Parent != null) + this.Register(); +#endif } private ObjectFactoryBase GetCurrentFactory(TypeRegistration registration) @@ -1510,8 +1539,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) @@ -1530,8 +1560,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; } @@ -1577,7 +1612,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) @@ -1606,6 +1647,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); } @@ -1772,7 +1817,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 } @@ -1785,6 +1830,8 @@ public void Dispose() { _RegisteredTypes.Dispose(); + + GC.SuppressFinalize(this); } #endregion