Scrutor 6.1.0
Scrutor  
 
Scrutor - I search or examine thoroughly; I probe, investigate or scrutinize
From scrūta, as the original sense of the verb was to search through trash. - https://en.wiktionary.org/wiki/scrutor
Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection
Installation
Install the Scrutor NuGet Package.
Package Manager Console
Install-Package Scrutor
.NET Core CLI
dotnet add package Scrutor
Usage
The library adds two extension methods to IServiceCollection:
- Scan- This is the entry point to set up your assembly scanning.
- Decorate- This method is used to decorate already registered services.
See Examples below for usage examples.
Examples
Scanning
var collection = new ServiceCollection();
collection.Scan(scan => scan
     // We start out with all types in the assembly of ITransientService
    .FromAssemblyOf<ITransientService>()
        // AddClasses starts out with all public, non-abstract types in this assembly.
        // These types are then filtered by the delegate passed to the method.
        // In this case, we filter out only the classes that are assignable to ITransientService.
        .AddClasses(classes => classes.AssignableTo<ITransientService>())
            // We then specify what type we want to register these classes as.
            // In this case, we want to register the types as all of its implemented interfaces.
            // So if a type implements 3 interfaces; A, B, C, we'd end up with three separate registrations.
            .AsImplementedInterfaces()
            // And lastly, we specify the lifetime of these registrations.
            .WithTransientLifetime()
        // Here we start again, with a new full set of classes from the assembly above.
        // This time, filtering out only the classes assignable to IScopedService.
        .AddClasses(classes => classes.AssignableTo<IScopedService>())
            // Now, we just want to register these types as a single interface, IScopedService.
            .As<IScopedService>()
            // And again, just specify the lifetime.
            .WithScopedLifetime()
        // Generic interfaces are also supported too, e.g. public interface IOpenGeneric<T> 
        .AddClasses(classes => classes.AssignableTo(typeof(IOpenGeneric<>)))
            .AsImplementedInterfaces()
        // And you scan generics with multiple type parameters too
        // e.g. public interface IQueryHandler<TQuery, TResult>
        .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))
            .AsImplementedInterfaces());
Scanning compiled view (UI) types
By default, Scrutor excludes compiler-generated types from the .AddClasses() type filters. When loading views from a framework such as Avalonia UI, we need to opt in to compiler-generated types, like this:
.AddClasses(classes => classes
    // Opt-in to compiler-generated types
    .WithAttribute<CompilerGeneratedAttribute>()
    // Optionally filter types to reduce number of service registrations.
    .InNamespaces("MyApp.Desktop.Views")
    .AssignableToAny(
        typeof(Window),
        typeof(UserControl)
    )
    .AsSelf()
    .WithSingletonLifetime()
With some UI frameworks, these compiler-generated views implement quite a few interfaces, so unless you need them, it's probably best to register these classes .AsSelf(); in other words, be very precise with your filters that accept compiler generated types.
Decoration
var collection = new ServiceCollection();
// First, add our service to the collection.
collection.AddSingleton<IDecoratedService, Decorated>();
// Then, decorate Decorated with the Decorator type.
collection.Decorate<IDecoratedService, Decorator>();
// Finally, decorate Decorator with the OtherDecorator type.
// As you can see, OtherDecorator requires a separate service, IService. We can get that from the provider argument.
collection.Decorate<IDecoratedService>((inner, provider) => new OtherDecorator(inner, provider.GetRequiredService<IService>()));
var serviceProvider = collection.BuildServiceProvider();
// When we resolve the IDecoratedService service, we'll get the following structure:
// OtherDecorator -> Decorator -> Decorated
var instance = serviceProvider.GetRequiredService<IDecoratedService>();
No packages depend on Scrutor.
.NET Framework 4.6.2
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
- Microsoft.Extensions.DependencyModel (>= 8.0.2)
.NET 8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
- Microsoft.Extensions.DependencyModel (>= 8.0.2)
.NET Standard 2.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.1)
- Microsoft.Extensions.DependencyModel (>= 8.0.2)
| Version | Downloads | Last updated | 
|---|---|---|
| 6.1.0 | 37 | 06/04/2025 | 
| 6.0.1 | 200 | 02/21/2025 | 
| 6.0.0 | 40 | 04/11/2025 | 
| 5.1.2 | 41 | 04/05/2025 | 
| 5.0.3 | 40 | 04/06/2025 | 
| 5.0.2 | 39 | 04/09/2025 | 
| 5.0.1 | 38 | 04/09/2025 | 
| 5.0.0 | 38 | 04/09/2025 | 
| 4.2.2 | 45 | 04/09/2025 | 
| 4.2.1 | 42 | 04/10/2025 | 
| 4.2.0 | 38 | 04/05/2025 | 
| 4.1.0 | 41 | 04/08/2025 | 
| 4.0.0 | 42 | 04/09/2025 | 
| 3.3.0 | 41 | 04/05/2025 | 
| 3.2.2 | 41 | 04/10/2025 | 
| 3.2.1 | 37 | 04/09/2025 | 
| 3.2.0 | 35 | 04/09/2025 | 
| 3.1.0 | 41 | 04/06/2025 | 
| 3.0.3 | 40 | 04/06/2025 | 
| 3.0.2 | 43 | 04/06/2025 | 
| 3.0.1 | 35 | 04/09/2025 | 
| 2.2.2 | 32 | 04/05/2025 | 
| 2.2.1 | 33 | 04/10/2025 | 
| 2.2.0 | 32 | 04/10/2025 | 
| 2.1.2 | 37 | 04/08/2025 | 
| 2.1.1 | 38 | 04/06/2025 | 
| 2.1.0 | 41 | 04/05/2025 | 
| 2.0.0 | 34 | 04/09/2025 | 
| 2.0.0-rc2 | 39 | 04/05/2025 | 
| 2.0.0-rc | 41 | 04/06/2025 | 
| 2.0.0-beta | 45 | 04/05/2025 | 
| 1.12.0 | 36 | 04/09/2025 | 
| 1.11.0 | 36 | 04/09/2025 | 
| 1.10.1 | 40 | 04/05/2025 | 
| 1.10.0 | 33 | 04/10/2025 | 
| 1.9.1 | 38 | 04/09/2025 | 
| 1.9.0 | 39 | 04/11/2025 | 
| 1.8.0 | 39 | 04/09/2025 | 
| 1.7.0 | 38 | 04/05/2025 | 
| 1.6.0 | 43 | 04/05/2025 | 
| 1.5.0 | 42 | 04/09/2025 | 
| 1.4.0 | 40 | 04/05/2025 | 
| 1.3.2 | 45 | 04/08/2025 | 
| 1.3.1 | 43 | 04/05/2025 | 
| 1.3.0 | 41 | 04/09/2025 | 
| 1.2.0 | 37 | 04/09/2025 | 
| 1.1.1 | 43 | 04/09/2025 | 
| 1.1.0 | 32 | 04/06/2025 | 
| 1.0.0 | 39 | 04/04/2025 |