diff --git a/src/Autofac/Core/Registration/ComponentRegistry.cs b/src/Autofac/Core/Registration/ComponentRegistry.cs index e2696d1d1..f7e75f6cc 100644 --- a/src/Autofac/Core/Registration/ComponentRegistry.cs +++ b/src/Autofac/Core/Registration/ComponentRegistry.cs @@ -260,17 +260,18 @@ public IEnumerable DecoratorsFor(IComponentRegistration return _decorators.GetOrAdd(registration, r => { + var result = new List(); + foreach (var service in r.Services) { if (service is DecoratorService || !(service is IServiceWithType swt)) continue; var decoratorService = new DecoratorService(swt.ServiceType); - return RegistrationsFor(decoratorService) - .OrderBy(d => d.GetRegistrationOrder()) - .ToArray(); + var decoratorRegistrations = RegistrationsFor(decoratorService); + result.AddRange(decoratorRegistrations); } - return Enumerable.Empty(); + return result.OrderBy(d => d.GetRegistrationOrder()).ToArray(); }); } diff --git a/test/Autofac.Test/Features/Decorators/DecoratorTests.cs b/test/Autofac.Test/Features/Decorators/DecoratorTests.cs index be8b2046e..485dac84c 100644 --- a/test/Autofac.Test/Features/Decorators/DecoratorTests.cs +++ b/test/Autofac.Test/Features/Decorators/DecoratorTests.cs @@ -13,6 +13,10 @@ public interface IService { } + public interface ISomeOtherService + { + } + public interface IDecoratedService : IService { IDecoratedService Decorated { get; } @@ -40,6 +44,11 @@ public ImplementorWithParameters(string parameter) } } + public class ImplementorWithSomeOtherService : IDecoratedService, ISomeOtherService + { + public IDecoratedService Decorated => this; + } + public abstract class Decorator : IDecoratedService { protected Decorator(IDecoratedService decorated) @@ -731,5 +740,22 @@ public void DecoratorAndDecoratedBothDisposedWhenSingleInstance() Assert.Equal(1, decorator.DisposeCallCount); Assert.Equal(1, decorated.DisposeCallCount); } + + [Theory] + [InlineData(typeof(IDecoratedService), typeof(ISomeOtherService))] + [InlineData(typeof(ISomeOtherService), typeof(IDecoratedService))] + public void DecoratorShouldBeAppliedRegardlessOfServiceOrder(Type firstService, Type secondService) + { + var builder = new ContainerBuilder(); + + builder.RegisterType().As(firstService, secondService); + builder.RegisterDecorator(); + var container = builder.Build(); + + var instance = container.Resolve(); + + Assert.IsType(instance); + Assert.IsType(instance.Decorated); + } } } diff --git a/test/Autofac.Test/Features/Decorators/OpenGenericDecoratorTests.cs b/test/Autofac.Test/Features/Decorators/OpenGenericDecoratorTests.cs index 78daf7a02..670379fe8 100644 --- a/test/Autofac.Test/Features/Decorators/OpenGenericDecoratorTests.cs +++ b/test/Autofac.Test/Features/Decorators/OpenGenericDecoratorTests.cs @@ -14,6 +14,10 @@ public interface IService { } + public interface ISomeOtherService + { + } + public interface IDecoratedService : IService { IDecoratedService Decorated { get; } @@ -41,6 +45,11 @@ public ImplementorWithParameters(string parameter) } } + public class ImplementorWithSomeOtherService : IDecoratedService, ISomeOtherService + { + public IDecoratedService Decorated => this; + } + public abstract class Decorator : IDecoratedService { protected Decorator(IDecoratedService decorated) @@ -658,5 +667,22 @@ public void DecoratorAndDecoratedBothDisposedWhenSingleInstance() Assert.Equal(1, decorator.DisposeCallCount); Assert.Equal(1, decorated.DisposeCallCount); } + + [Theory] + [InlineData(typeof(IDecoratedService<>), typeof(ISomeOtherService<>))] + [InlineData(typeof(ISomeOtherService<>), typeof(IDecoratedService<>))] + public void DecoratorShouldBeAppliedRegardlessOfServiceOrder(Type firstService, Type secondService) + { + var builder = new ContainerBuilder(); + + builder.RegisterGeneric(typeof(ImplementorWithSomeOtherService<>)).As(firstService, secondService); + builder.RegisterGenericDecorator(typeof(DecoratorA<>), typeof(IDecoratedService<>)); + var container = builder.Build(); + + var instance = container.Resolve>(); + + Assert.IsType>(instance); + Assert.IsType>(instance.Decorated); + } } }