From 634c0a063c914b03a1729e320f889adc70b9bb38 Mon Sep 17 00:00:00 2001 From: Vladimir Pecanac Date: Sat, 15 Aug 2026 17:22:27 +0200 Subject: [PATCH] IntroductionToScrutorInDotNet: retarget net10.0, bump Scrutor to 7.0.0, add pitfalls tests Scrutor 7.0.0 removed FromCallingAssembly(); switch both scans to FromAssembliesOf(typeof(Program)). Bump all packages to current versions. Add ScrutorPitfallsTests covering duplicate-scan append, RegistrationStrategy.Skip, default transient lifetime, DecorationException on unregistered decorate, and open-generic decoration of the scanned repository. --- ...oductionToScrutorInDotNet.Customers.csproj | 2 +- .../IntroductionToScrutorInDotNet.csproj | 8 +- .../IntroductionToScrutorInDotNet/Program.cs | 4 +- .../Tests/ScrutorPitfallsTests.cs | 85 +++++++++++++++++++ .../Tests/Tests.csproj | 13 +-- 5 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/ScrutorPitfallsTests.cs diff --git a/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.Customers/IntroductionToScrutorInDotNet.Customers.csproj b/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.Customers/IntroductionToScrutorInDotNet.Customers.csproj index 6836c6808f..e0ad4b5540 100644 --- a/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.Customers/IntroductionToScrutorInDotNet.Customers.csproj +++ b/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.Customers/IntroductionToScrutorInDotNet.Customers.csproj @@ -1,7 +1,7 @@ - net7.0 + net10.0 enable enable diff --git a/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.csproj b/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.csproj index 47db4ffab3..c63dfc5e42 100644 --- a/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.csproj +++ b/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet.csproj @@ -1,15 +1,15 @@ - net7.0 + net10.0 enable enable - - - + + + diff --git a/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/Program.cs b/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/Program.cs index ac49e4ca63..c41b6c8ad7 100644 --- a/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/Program.cs +++ b/dependency-injection-tools/IntroductionToScrutorInDotNet/IntroductionToScrutorInDotNet/Program.cs @@ -7,7 +7,7 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.Scan(selector => selector - .FromCallingAssembly() + .FromAssembliesOf(typeof(Program)) .AddClasses( classSelector => classSelector.InNamespaces("IntroductionToScrutorInDotNet.Services.Implementations") @@ -24,7 +24,7 @@ ); builder.Services.Scan(selector => selector - .FromCallingAssembly() + .FromAssembliesOf(typeof(Program)) .AddClasses(classSelector => classSelector.AssignableTo(typeof(IRepository<>))) .UsingRegistrationStrategy(RegistrationStrategy.Skip) .AsImplementedInterfaces()); diff --git a/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/ScrutorPitfallsTests.cs b/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/ScrutorPitfallsTests.cs new file mode 100644 index 0000000000..76aa5d9171 --- /dev/null +++ b/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/ScrutorPitfallsTests.cs @@ -0,0 +1,85 @@ +using IntroductionToScrutorInDotNet.Entities; +using IntroductionToScrutorInDotNet.Repositories; +using IntroductionToScrutorInDotNet.Repositories.Decorators; +using IntroductionToScrutorInDotNet.Repositories.Implementations; +using Microsoft.Extensions.DependencyInjection; +using Scrutor; + +namespace Tests; + +public class ScrutorPitfallsTests +{ + private static ServiceCollection ScanRepositories(RegistrationStrategy? strategy = null) + { + var services = new ServiceCollection(); + services.Scan(selector => selector + .FromAssembliesOf(typeof(UserRepository)) + .AddClasses(classSelector => classSelector.AssignableTo(typeof(IRepository<>))) + .UsingRegistrationStrategy(strategy ?? RegistrationStrategy.Append) + .AsImplementedInterfaces()); + return services; + } + + [Fact] + public void GivenTwoScans_WhenAppending_ThenRegistrationIsDuplicated() + { + var services = ScanRepositories(); + services.Scan(selector => selector + .FromAssembliesOf(typeof(UserRepository)) + .AddClasses(classSelector => classSelector.AssignableTo(typeof(IRepository<>))) + .AsImplementedInterfaces()); + + var count = services.Count(descriptor => descriptor.ServiceType == typeof(IRepository)); + + Assert.Equal(2, count); + } + + [Fact] + public void GivenTwoScans_WhenUsingSkipStrategy_ThenRegistrationIsNotDuplicated() + { + var services = ScanRepositories(RegistrationStrategy.Skip); + services.Scan(selector => selector + .FromAssembliesOf(typeof(UserRepository)) + .AddClasses(classSelector => classSelector.AssignableTo(typeof(IRepository<>))) + .UsingRegistrationStrategy(RegistrationStrategy.Skip) + .AsImplementedInterfaces()); + + var count = services.Count(descriptor => descriptor.ServiceType == typeof(IRepository)); + + Assert.Equal(1, count); + } + + [Fact] + public void GivenScannedRegistration_WhenLifetimeIsNotSpecified_ThenItIsTransient() + { + var services = ScanRepositories(); + + var descriptor = services.First(d => d.ServiceType == typeof(IRepository)); + + Assert.Equal(ServiceLifetime.Transient, descriptor.Lifetime); + } + + [Fact] + public void GivenNoPriorRegistration_WhenDecorating_ThenDecorationExceptionIsThrown() + { + var services = new ServiceCollection(); + + var exception = Assert.Throws(() => + services.Decorate, RepositoryLoggerDecorator>()); + + Assert.Contains("Could not find any registered services", exception.Message); + } + + [Fact] + public void GivenScannedRepository_WhenDecoratingTheOpenGeneric_ThenTheDecoratorResolves() + { + var services = ScanRepositories(); + + services.Decorate(typeof(IRepository<>), typeof(RepositoryLoggerDecorator<>)); + + var provider = services.BuildServiceProvider(); + var resolved = provider.GetRequiredService>(); + + Assert.IsType>(resolved); + } +} diff --git a/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/Tests.csproj b/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/Tests.csproj index 2690e1934e..b02aba6a88 100644 --- a/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/Tests.csproj +++ b/dependency-injection-tools/IntroductionToScrutorInDotNet/Tests/Tests.csproj @@ -1,22 +1,23 @@ - net7.0 + net10.0 enable enable false + true - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all