From 80bfa368c119c58bf8f05fce4d1d6072f3975664 Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Tue, 24 May 2011 15:52:15 -0700 Subject: [PATCH 1/3] Reversing order of IEnumerable resolved from IoC Components are registered in dependency/priority order and this is also the order events and hooks should fire. The default order of Autofac is opposite what we need for enumerable services. The behavior of resolving a single TService is unchanged - the last-registered of TService is the only returned. --HG-- branch : 1.x extra : transplant_source : %87%22%FC%84%A1%0FP%3C%20w%B4%1EQ%CC%90%20%97%C1%EC%BF --- .../Environment/CollectionOrderModule.cs | 23 +++++++++++++++++++ src/Orchard/Environment/OrchardStarter.cs | 1 + src/Orchard/Orchard.Framework.csproj | 1 + 3 files changed, 25 insertions(+) create mode 100644 src/Orchard/Environment/CollectionOrderModule.cs diff --git a/src/Orchard/Environment/CollectionOrderModule.cs b/src/Orchard/Environment/CollectionOrderModule.cs new file mode 100644 index 000000000..c3046177d --- /dev/null +++ b/src/Orchard/Environment/CollectionOrderModule.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections; +using Autofac.Core; + +namespace Orchard.Environment { + internal class CollectionOrderModule : IModule { + public void Configure(IComponentRegistry componentRegistry) { + componentRegistry.Registered += (s, e) => { + // only bother watching enumerable resolves + var limitType = e.ComponentRegistration.Activator.LimitType; + if (typeof(IEnumerable).IsAssignableFrom(limitType)) { + e.ComponentRegistration.Activated += (s2, e2) => { + // Autofac's IEnumerable feature returns an Array + if (e2.Instance is Array) { + // Orchard needs FIFO, not FILO, component order + Array.Reverse((Array)e2.Instance); + } + }; + } + }; + } + } +} diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index 5f4b1e1c9..41fd63bda 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -31,6 +31,7 @@ namespace Orchard.Environment { public static class OrchardStarter { public static IContainer CreateHostContainer(Action registrations) { var builder = new ContainerBuilder(); + builder.RegisterModule(new CollectionOrderModule()); builder.RegisterModule(new LoggingModule()); builder.RegisterModule(new EventsModule()); builder.RegisterModule(new CacheModule()); diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 35b429556..2d0945bd4 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -173,6 +173,7 @@ + From 08ec2d367497366278ba5c7091a55668391a4e3f Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Tue, 24 May 2011 17:35:31 -0700 Subject: [PATCH 2/3] Adding tests to assert Autofac's expected behavior --HG-- branch : 1.x --- .../Environment/OrchardStarterTests.cs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/Orchard.Tests/Environment/OrchardStarterTests.cs b/src/Orchard.Tests/Environment/OrchardStarterTests.cs index b24eebe67..7d22ca68c 100644 --- a/src/Orchard.Tests/Environment/OrchardStarterTests.cs +++ b/src/Orchard.Tests/Environment/OrchardStarterTests.cs @@ -1,4 +1,6 @@ -using System.Web.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Web.Mvc; using Autofac; using NUnit.Framework; using Orchard.Environment; @@ -11,5 +13,34 @@ namespace Orchard.Tests.Environment { var host = OrchardStarter.CreateHost(b => b.RegisterInstance(new ControllerBuilder())); Assert.That(host, Is.TypeOf()); } + + [Test] + public void ContainerResolvesServicesInSameOrderTheyAreRegistered() { + var container = OrchardStarter.CreateHostContainer(builder => { + builder.RegisterType().As(); + builder.RegisterType().As(); + }); + var services = container.Resolve>(); + Assert.That(services.Count(), Is.EqualTo(2)); + Assert.That(services.First(), Is.TypeOf()); + Assert.That(services.Last(), Is.TypeOf()); + } + + [Test] + public void MostRecentlyRegisteredServiceReturnsFromSingularResolve() { + var container = OrchardStarter.CreateHostContainer(builder => { + builder.RegisterType().As(); + builder.RegisterType().As(); + }); + var service = container.Resolve(); + Assert.That(service, Is.Not.Null); + Assert.That(service, Is.TypeOf()); + } + + public interface IServiceA {} + + public class Component1 : IServiceA {} + + public class Component2 : IServiceA {} } -} +} \ No newline at end of file From c771be816c54ac1674270686c57609c324718b4a Mon Sep 17 00:00:00 2001 From: Louis DeJardin Date: Tue, 24 May 2011 17:39:47 -0700 Subject: [PATCH 3/3] Using better argument variable names --HG-- branch : 1.x --- src/Orchard/Environment/CollectionOrderModule.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Orchard/Environment/CollectionOrderModule.cs b/src/Orchard/Environment/CollectionOrderModule.cs index c3046177d..bf48644df 100644 --- a/src/Orchard/Environment/CollectionOrderModule.cs +++ b/src/Orchard/Environment/CollectionOrderModule.cs @@ -5,15 +5,15 @@ using Autofac.Core; namespace Orchard.Environment { internal class CollectionOrderModule : IModule { public void Configure(IComponentRegistry componentRegistry) { - componentRegistry.Registered += (s, e) => { + componentRegistry.Registered += (sender, registered) => { // only bother watching enumerable resolves - var limitType = e.ComponentRegistration.Activator.LimitType; + var limitType = registered.ComponentRegistration.Activator.LimitType; if (typeof(IEnumerable).IsAssignableFrom(limitType)) { - e.ComponentRegistration.Activated += (s2, e2) => { + registered.ComponentRegistration.Activated += (sender2, activated) => { // Autofac's IEnumerable feature returns an Array - if (e2.Instance is Array) { + if (activated.Instance is Array) { // Orchard needs FIFO, not FILO, component order - Array.Reverse((Array)e2.Instance); + Array.Reverse((Array)activated.Instance); } }; }