MintPlayer.SourceGenerators 10.21.0

dotnet add package MintPlayer.SourceGenerators --version 10.21.0
                    
NuGet\Install-Package MintPlayer.SourceGenerators -Version 10.21.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MintPlayer.SourceGenerators" Version="10.21.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MintPlayer.SourceGenerators" Version="10.21.0" />
                    
Directory.Packages.props
<PackageReference Include="MintPlayer.SourceGenerators">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MintPlayer.SourceGenerators --version 10.21.0
                    
#r "nuget: MintPlayer.SourceGenerators, 10.21.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MintPlayer.SourceGenerators@10.21.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MintPlayer.SourceGenerators&version=10.21.0
                    
Install as a Cake Addin
#tool nuget:?package=MintPlayer.SourceGenerators&version=10.21.0
                    
Install as a Cake Tool

Dependency-Injection generators

This library contains source-generators to simplify dependency-injection in your application

Getting started

You need to install both MintPlayer.SourceGenerators and MintPlayer.SourceGenerators.Attributes packages in your project.

Service-registration

Place this class in your abstractions library:

public interface ICustomerService { }

Place this class in your implementation library:

[Register(typeof(ICustomerService), ServiceLifetime.Scoped)]
internal class CustomerService : ICustomerService { }

Now you get an extension method generated for you, which will register all services for you:

var services = new ServiceCollection()
    .AddMyCompanyServices()  // Method name derived from assembly name
    .BuildServiceProvider();

Method Name Resolution

The generated method name follows this precedence:

  1. Explicit hint on [Register] attribute (e.g., "CoreServices") → AddCoreServices()
  2. Assembly-level configuration via [assembly: ServiceRegistrationConfiguration]
  3. Assembly name (default) - sanitized and prefixed with "Add" (e.g., MyCompany.ServicesAddMyCompanyServices())

Assembly-Level Configuration

You can configure the default method name and accessibility at the assembly level:

using MintPlayer.SourceGenerators.Attributes;

[assembly: ServiceRegistrationConfiguration(
    DefaultMethodName = "MyServices",
    DefaultAccessibility = EGeneratedAccessibility.Internal
)]

This will generate AddMyServices() as an internal method for all services without an explicit method hint.

Explicit Method Hints

You can still specify a method hint on individual registrations to group services:

[Register(typeof(ICustomerService), ServiceLifetime.Scoped, "DemoServices")]
internal class CustomerService : ICustomerService { }

[Register(typeof(IProductService), ServiceLifetime.Scoped, "DemoServices")]
internal class ProductService : IProductService { }

This generates:

var services = new ServiceCollection()
    .AddDemoServices()  // Contains CustomerService and ProductService
    .BuildServiceProvider();

Registering Third-Party Types

You can register types from NuGet packages or external libraries at the assembly level:

using MintPlayer.SourceGenerators.Attributes;

// Self-registration (implementation = service type)
[assembly: Register(typeof(ThirdPartyClass), ServiceLifetime.Singleton)]

// Interface + implementation registration
[assembly: Register(typeof(IExternalService), typeof(ExternalServiceImpl), ServiceLifetime.Scoped)]

This generates:

public static IServiceCollection AddMyAssembly(this IServiceCollection services)
{
    return services
        .AddSingleton<ThirdPartyClass>()
        .AddScoped<IExternalService, ExternalServiceImpl>();
}

Registration Patterns Summary

Pattern Target Example
Self-registration Class [Register(ServiceLifetime.Scoped)]
Interface registration Class [Register(typeof(IService), ServiceLifetime.Scoped)]
Third-party self-registration Assembly [assembly: Register(typeof(Impl), ServiceLifetime.Scoped)]
Third-party interface registration Assembly [assembly: Register(typeof(IService), typeof(Impl), ServiceLifetime.Scoped)]

Registration Diagnostics

Rule ID Severity Description
REGISTER001 Error Assembly-level [Register] requires at least the implementation type
REGISTER002 Error Class-level [Register] should not specify implementation type

Dependency Injection

Inject a registered service anywhere:

public partial class CustomerController {
    [Inject] private readonly ICustomerService customerService;
}

The source-generator will generate the constructor for you. It supports DI when using inheritance too.

Post-Construction Initialization

If you need to run initialization logic after all dependencies are injected, use the [PostConstruct] attribute:

public partial class CustomerController {
    [Inject] private readonly ICustomerService customerService;
    [Inject] private readonly ILogger<CustomerController> logger;

    [PostConstruct]
    private void OnInitialized()
    {
        logger.LogInformation("CustomerController initialized with {Service}", customerService.GetType().Name);
    }
}

The [PostConstruct] method will be called automatically at the end of the generated constructor, after all field assignments are complete.

Rules:

  • The method must be parameterless
  • Only one [PostConstruct] method is allowed per class
  • The method cannot be static
  • Each class in an inheritance hierarchy can have its own [PostConstruct] method (base class method runs first)
  • Nested classes each have their own scope for [PostConstruct]

Diagnostics: | Rule ID | Severity | Description | |---------|----------|-------------| | INJECT001 | Error | PostConstruct method must be parameterless | | INJECT002 | Error | Only one PostConstruct method allowed per class | | INJECT003 | Error | PostConstruct method cannot be static | | INJECT004 | Warning | PostConstruct method in class without [Inject] members |

Configuration Binding

Simplify reading configuration values with [Config], [ConnectionString], and [Options] attributes:

public partial class DatabaseService
{
    // Required config values (throws if missing)
    [Config("Database:Type")]
    private readonly DatabaseType databaseType;

    // Optional with default value
    [Config("Database:MaxRetries", DefaultValue = 3)]
    private readonly int maxRetries;

    // TimeSpan parsing
    [Config("Database:Timeout")]
    private readonly TimeSpan timeout;

    // Connection string
    [ConnectionString("DefaultConnection")]
    private readonly string connectionString;

    // Nullable = optional (won't throw if missing)
    [ConnectionString("OptionalDb")]
    private readonly string? optionalConnection;
}

IOptions Pattern

public partial class EmailService
{
    [Options("Email")]
    private readonly IOptions<EmailSettings> emailOptions;

    [Options("Customer")]
    private readonly IOptionsSnapshot<CustomerConfig> customerOptions;

    [Options("Features")]
    private readonly IOptionsMonitor<FeatureFlags> featureFlags;
}

IConfiguration Deduplication

When you inject IConfiguration explicitly, the generator reuses it:

public partial class ConfigAwareService
{
    [Inject] private readonly IConfiguration configuration;

    [Config("App:Name")]
    private readonly string appName;  // Uses 'configuration' field

    public string GetCustomValue(string key) => configuration[key];
}

Supported Types

Category Types
Primitives string, bool, char, byte, short, int, long, float, double, decimal
Nullable int?, bool?, string?, etc.
Enums Any enum type
Date/Time DateTime, DateTimeOffset, TimeSpan, DateOnly, TimeOnly
Other Guid, Uri
Complex POCO classes, arrays, List<T>

Configuration Diagnostics

Rule ID Severity Description
CONFIG001 Error Class must be partial
CONFIG002 Error Empty configuration key
CONFIG003 Error Unsupported field type
CONFIG006 Error Conflicting [Config] and [ConnectionString]
CONFIG008 Error Conflicting [Config] and [Inject]
CONNSTR001 Error Empty connection string name
CONNSTR002 Error [ConnectionString] requires string type
OPTIONS001 Error Invalid options type
OPTIONS003 Error Conflicting [Options] and [Inject]

Interface Implementation

There's also an analyzer that will check if all public class members are known on the implemented interface. The analyzer provides a code-fix to add the missing members.

public interface ICustomerService { }

[Register(typeof(ICustomerService), ServiceLifetime.Scoped)]
internal class CustomerService : ICustomerService {
    public Task<Customer> GetCustomer(int id) => throw new NotImplementedException();
}

This also works when the interface resides in an abstractions-library and the class resides in an implementation-library. Which is why this analyzer is so powerful.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.21.0 50 8/27/2026
10.20.1 47 8/27/2026
10.20.0 403 6/5/2026
10.19.0 778 4/3/2026
10.18.0 163 3/26/2026
10.17.0 650 2/14/2026
10.16.1 283 1/25/2026
10.16.0 128 1/25/2026
10.15.0 135 1/24/2026
10.14.1 125 1/20/2026
10.14.0 132 1/19/2026
10.13.0 218 1/19/2026
10.12.0 132 1/19/2026
10.11.1 139 1/18/2026
10.11.0 128 1/18/2026
10.10.1 145 1/12/2026
10.10.0 138 1/12/2026
10.9.0 138 1/12/2026
10.8.0 213 12/24/2025
10.7.0 312 11/13/2025
Loading failed