From a130074d4431fdd89639bfad5f2305bf2436a9c7 Mon Sep 17 00:00:00 2001 From: Oleksandr Tolstikov Date: Mon, 13 Sep 2021 23:25:49 +0300 Subject: [PATCH 1/2] - Fix isues #148 #117 --- .../ServiceCollectionExtensions.Decoration.cs | 11 ++++- test/Scrutor.Tests/DecorationTests.cs | 40 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/Scrutor/ServiceCollectionExtensions.Decoration.cs b/src/Scrutor/ServiceCollectionExtensions.Decoration.cs index 9be40aee..8e27b0b9 100644 --- a/src/Scrutor/ServiceCollectionExtensions.Decoration.cs +++ b/src/Scrutor/ServiceCollectionExtensions.Decoration.cs @@ -341,9 +341,16 @@ private static object GetInstance(this IServiceProvider provider, ServiceDescrip return descriptor.ImplementationInstance; } - if (descriptor.ImplementationType != null) + // Not suppose to be abstract. + Type implementationType = descriptor.ImplementationType; + if (implementationType != null) { - return provider.GetServiceOrCreateInstance(descriptor.ImplementationType); + if (implementationType != descriptor.ServiceType) + return provider.GetServiceOrCreateInstance(descriptor.ImplementationType); + + // Since implementationType is equal to ServiceType we need explicitly create an implementation type through reflections in order to avoid infinite recursion. + // Should not cause issue with singletons, since singleton will be a decorator and after this fact we can don't care about lifecycle of decorable service (for sure, if IDisposable of decorator disposes underlying type:)) + return provider.CreateInstance(implementationType); } return descriptor.ImplementationFactory(provider); diff --git a/test/Scrutor.Tests/DecorationTests.cs b/test/Scrutor.Tests/DecorationTests.cs index ed281ded..ff70d564 100644 --- a/test/Scrutor.Tests/DecorationTests.cs +++ b/test/Scrutor.Tests/DecorationTests.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; using System.Linq; +using static Scrutor.Tests.DecorationTests; namespace Scrutor.Tests { @@ -217,8 +218,47 @@ public void DecoratingNonRegisteredServiceThrows() Assert.Throws(() => ConfigureProvider(services => services.Decorate())); } + [Fact] + public void Issue148_Decorate_IsAbleToDecorateConcreateTypes() + { + var sp = ConfigureProvider(sc => + { + sc + .AddTransient() + .AddTransient() + .Decorate(); + }); + + var result = sp.GetService() as Decorator2; + + Assert.NotNull(result); + Assert.NotNull(result.Inner); + Assert.NotNull(result.Inner.Dependency); + } + public interface IDecoratedService { } + public class DecoratedService + { + public DecoratedService(IService dependency) + { + Dependency = dependency; + } + + public IService Dependency { get; } + } + + public class Decorator2 : DecoratedService + { + public Decorator2(DecoratedService decoratedService) + : base(null) + { + Inner = decoratedService; + } + + public DecoratedService Inner { get; } + } + public interface IService { } private class SomeRandomService : IService { } From d841d339efa480b2182c2c9f7e85dd651a213d70 Mon Sep 17 00:00:00 2001 From: Oleksandr Tolstikov Date: Tue, 14 Sep 2021 10:13:06 +0300 Subject: [PATCH 2/2] - cleanup --- src/Scrutor/ServiceCollectionExtensions.Decoration.cs | 2 +- test/Scrutor.Tests/DecorationTests.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Scrutor/ServiceCollectionExtensions.Decoration.cs b/src/Scrutor/ServiceCollectionExtensions.Decoration.cs index 8e27b0b9..3716565f 100644 --- a/src/Scrutor/ServiceCollectionExtensions.Decoration.cs +++ b/src/Scrutor/ServiceCollectionExtensions.Decoration.cs @@ -346,7 +346,7 @@ private static object GetInstance(this IServiceProvider provider, ServiceDescrip if (implementationType != null) { if (implementationType != descriptor.ServiceType) - return provider.GetServiceOrCreateInstance(descriptor.ImplementationType); + return provider.GetServiceOrCreateInstance(implementationType); // Since implementationType is equal to ServiceType we need explicitly create an implementation type through reflections in order to avoid infinite recursion. // Should not cause issue with singletons, since singleton will be a decorator and after this fact we can don't care about lifecycle of decorable service (for sure, if IDisposable of decorator disposes underlying type:)) diff --git a/test/Scrutor.Tests/DecorationTests.cs b/test/Scrutor.Tests/DecorationTests.cs index ff70d564..e30b7242 100644 --- a/test/Scrutor.Tests/DecorationTests.cs +++ b/test/Scrutor.Tests/DecorationTests.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.DependencyInjection; using Xunit; using System.Linq; -using static Scrutor.Tests.DecorationTests; namespace Scrutor.Tests {