From: <sv...@ca...> - 2006-06-29 22:05:37
|
User: ayende Date: 2006/06/29 05:59 PM Modified: /branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/ComponentActivator/ DefaultComponentActivator.cs /branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Context/ CreationContext.cs /branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/ AbstractHandler.cs, DefaultHandler.cs, IExposeDependencyInfo.cs /branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/ CircularDependencyTests.cs /branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/Components/ DotNet2Components.cs /branches/IoC-DetectCyclesInDependencies/Castle.Windsor/ Castle.Windsor-2-0.csproj Log: Fixed failing tests. File Changes: Directory: /branches/IoC-DetectCyclesInDependencies/Castle.Windsor/ =================================================================== File [modified]: Castle.Windsor-2-0.csproj Delta lines: +1 -1 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.Windsor/Castle.Windsor-2-0.csproj 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.Windsor/Castle.Windsor-2-0.csproj 2006-06-29 21:58:59 UTC (rev 2017) @@ -76,7 +76,7 @@ <ItemGroup> <Reference Include="Castle.DynamicProxy, Version=1.1.5.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\..\Castle\Tools\DynamicProxy\bin\Castle.DynamicProxy.dll</HintPath> + <HintPath>..\..\build\net-2.0\Castle.DynamicProxy.dll</HintPath> </Reference> <Reference Include="System"> <Name>System</Name> Directory: /branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/ ========================================================================= File [modified]: CircularDependencyTests.cs Delta lines: +22 -5 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/CircularDependencyTests.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/CircularDependencyTests.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -18,12 +18,13 @@ using Castle.Windsor.Tests.Components; using NUnit.Framework; + using Castle.MicroKernel.Handlers; [TestFixture] public class CircularDependencyTests { [Test] - [ExpectedException(typeof(CircularDependecyException), @"A cycle was detected when trying to create a service. The depedency graph that resulted in a cycle is: + [ExpectedException(typeof(CircularDependecyException), @"A cycle was detected when trying to create a service. The dependency graph that resulted in a cycle is: - Service dependency 'view' type 'Castle.Windsor.Tests.Components.IView' for Void .ctor(Castle.Windsor.Tests.Components.IView) in type Castle.Windsor.Tests.Components.Controller - Service dependency 'Controller' type 'Castle.Windsor.Tests.Components.IController' for Castle.Windsor.Tests.Components.IController Controller in type Castle.Windsor.Tests.Components.View + Service dependency 'view' type 'Castle.Windsor.Tests.Components.IView' for Void .ctor(Castle.Windsor.Tests.Components.IView) in Castle.Windsor.Tests.Components.Controller @@ -38,10 +39,26 @@ } [Test] - [ExpectedException(typeof(CircularDependecyException), @"A cycle was detected when trying to create a service. The depedency graph that resulted in a cycle is: - - Service dependency 'view' type 'Castle.Windsor.Tests.Components.IView' for Void .ctor(Castle.Windsor.Tests.Components.IView) in type Castle.Windsor.Tests.Components.Controller - - Service dependency 'Controller' type 'Castle.Windsor.Tests.Components.IController' for Castle.Windsor.Tests.Components.IController Controller in type Castle.Windsor.Tests.Components.View - + Service dependency 'view' type 'Castle.Windsor.Tests.Components.IView' for Void .ctor(Castle.Windsor.Tests.Components.IView) in Castle.Windsor.Tests.Components.Controller + [ExpectedException(typeof(HandlerException), @"Can't create component 'compA' as it has dependencies to be satisfied. +compA is waiting for the following dependencies: + +Services: +- Castle.Windsor.Tests.Components.CompB which was registered but is also waiting for dependencies. + +compB is waiting for the following dependencies: + +Services: +- Castle.Windsor.Tests.Components.CompC which was registered but is also waiting for dependencies. + +compC is waiting for the following dependencies: + +Services: +- Castle.Windsor.Tests.Components.CompD which was registered but is also waiting for dependencies. + +compD is waiting for the following dependencies: + +Services: +- Castle.Windsor.Tests.Components.CompA which was registered but is also waiting for dependencies. ")] public void ThrowsACircularDependencyException2() { Directory: /branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/ComponentActivator/ ========================================================================================== File [modified]: DefaultComponentActivator.cs Delta lines: +8 -2 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/ComponentActivator/DefaultComponentActivator.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/ComponentActivator/DefaultComponentActivator.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -198,8 +198,11 @@ foreach(DependencyModel dependency in constructor.Dependencies) { - context.AddDependency(constructor.Constructor, dependency); + object dependencyKey = context.TrackDependency(constructor.Constructor, dependency); object value = Kernel.Resolver.Resolve(context, Model, dependency); + + //The depdency was resolved successfully, we can stop tracking it. + context.RemoveDependencyTracking(dependencyKey); arguments[index] = value; signature[index++] = dependency.TargetType; } @@ -211,9 +214,12 @@ { foreach(PropertySet property in Model.Properties) { - context.AddDependency(property.Property, property.Dependency); + object dependencyKey = context.TrackDependency(property.Property, property.Dependency); object value = Kernel.Resolver.Resolve(context, Model, property.Dependency); + //The depdency was resolved successfully, we can stop tracking it. + context.RemoveDependencyTracking(dependencyKey); + if (value == null) continue; MethodInfo setMethod = property.Property.GetSetMethod(); Directory: /branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/Components/ ==================================================================================== File [modified]: DotNet2Components.cs Delta lines: +0 -7 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/Components/DotNet2Components.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.Windsor.Tests/Components/DotNet2Components.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -52,14 +52,7 @@ public class ReviewerRepository : DemoRepository<IReviewer> { string name; - ICache<IReviewer> cache; - public ICache<IReviewer> Cache - { - get { return cache; } - set { cache = value; } - } - public string Name { get { return name; } Directory: /branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Context/ =============================================================================== File [modified]: CreationContext.cs Delta lines: +21 -4 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Context/CreationContext.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Context/CreationContext.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -39,7 +39,11 @@ this.dependencies = new ArrayList(dependencies); } - public void AddDependency(MemberInfo info, DependencyModel dependencyModel) + /// <summary> + /// Track dependencies and guards against circular dependencies. + /// </summary> + /// <returns>A dependency key that can be used to remove the dependency if it was resolved correctly.</returns> + public object TrackDependency(MemberInfo info, DependencyModel dependencyModel) { if (dependencies.Contains(dependencyModel)) { @@ -57,10 +61,20 @@ throw new CircularDependecyException(sb.ToString()); } - - dependencies.Add(new DependencyKey(dependencyModel, info)); + + object trackingKey = new DependencyKey(dependencyModel, info); + dependencies.Add(trackingKey); + return trackingKey; } + /// <summary> + /// Removes a dependency that was resolved successfully. + /// </summary> + public void RemoveDependencyTracking(object key) + { + dependencies.Remove(key); + } + public ICollection Dependencies { get { return dependencies; } @@ -107,9 +121,12 @@ get { return info; } } + public override bool Equals(object obj) { - return dependencyModel.Equals(obj); + if ( Object.ReferenceEquals(this, obj)) + return true; + return dependencyModel.Equals(obj); } public override int GetHashCode() Directory: /branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/ ================================================================================ File [modified]: AbstractHandler.cs Delta lines: +8 -3 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/AbstractHandler.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/AbstractHandler.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -340,10 +340,15 @@ /// this handler is waiting for. /// </summary> /// <returns></returns> - public String ObtainDependencyDetails() + public String ObtainDependencyDetails(IList dependenciesChecked) { if (this.CurrentState == HandlerState.Valid) return String.Empty; + if (dependenciesChecked.Contains(this)) + return String.Empty; + + dependenciesChecked.Add(this); + StringBuilder sb = new StringBuilder(); sb.AppendFormat( "\r\n{0} is waiting for the following dependencies: \r\n", ComponentModel.Name ); @@ -375,7 +380,7 @@ if (info != null) { - sb.Append(info.ObtainDependencyDetails()); + sb.Append(info.ObtainDependencyDetails(dependenciesChecked)); } } } @@ -402,7 +407,7 @@ if (info != null) { - sb.Append(info.ObtainDependencyDetails()); + sb.Append(info.ObtainDependencyDetails(dependenciesChecked)); } } } File [modified]: DefaultHandler.cs Delta lines: +3 -1 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/DefaultHandler.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/DefaultHandler.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -17,6 +17,7 @@ using System; using Castle.Model; + using System.Collections; /// <summary> /// Summary description for DefaultHandler. @@ -52,7 +53,8 @@ if (CurrentState == HandlerState.WaitingDependency) { String message = String.Format("Can't create component '{1}' " + - "as it has dependencies to be satisfied. {0}", ObtainDependencyDetails(), + "as it has dependencies to be satisfied. {0}", + ObtainDependencyDetails(new ArrayList()), ComponentModel.Name); throw new HandlerException(message); File [modified]: IExposeDependencyInfo.cs Delta lines: +3 -2 =================================================================== --- branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/IExposeDependencyInfo.cs 2006-06-29 08:30:34 UTC (rev 2016) +++ branches/IoC-DetectCyclesInDependencies/Castle.MicroKernel/Handlers/IExposeDependencyInfo.cs 2006-06-29 21:58:59 UTC (rev 2017) @@ -15,6 +15,7 @@ namespace Castle.MicroKernel.Handlers { using System; +using System.Collections; /// <summary> /// Might be implemented by a handler @@ -26,8 +27,8 @@ /// <summary> /// Returns human readable list of dependencies /// this handler is waiting for. + /// <param name="dependenciesChecked">list of the dependecies that was already checked, used to avoid cycles.</param> /// </summary> - /// <returns></returns> - String ObtainDependencyDetails(); + String ObtainDependencyDetails(IList dependenciesChecked); } } |