# Splat.DI.SourceGenerator
**Repository Path**: mirrors_reactiveui/Splat.DI.SourceGenerator
## Basic Information
- **Project Name**: Splat.DI.SourceGenerator
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-01-28
- **Last Updated**: 2026-02-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[](https://github.com/reactiveui/Splat.DI.SourceGenerator/actions/workflows/ci-build.yml)
[](https://codecov.io/gh/reactiveui/Splat.DI.SourceGenerator)
[](https://www.nuget.org/packages/Splat.DependencyInjection.SourceGenerator/)
[](https://www.nuget.org/packages/Splat.DependencyInjection.SourceGenerator/)
# Splat Dependency Injection Source Generator
A high-performance C# source generator that produces compile-time dependency injection registrations for [Splat](https://github.com/reactiveui/splat). Eliminates runtime reflection, provides full native AOT support, and includes intelligent analyzers with automatic code fixes.
## What does it do?
This source generator produces dependency injection registrations for Splat at compile-time based on your constructor and property injection requirements. It uses an incremental source generator to provide fast builds with zero runtime reflection overhead.
Key features:
- Zero reflection - All registrations generated at compile-time
- Native AOT compatible - Works with trimming and AOT compilation
- Built-in analyzers - Real-time diagnostics and automatic code fixes
- Constructor injection - Automatic dependency resolution
- Property injection - Attribute-based property initialization
- Lazy singletons - Thread-safe lazy initialization with configurable modes
- Contract support - Named registrations for multiple implementations
- Incremental compilation - Fast builds that only regenerate when needed
## How do I install?
[Always Be NuGetting](https://nuget.org/packages/Splat.DependencyInjection.SourceGenerator/). Package contains:
| Package | NuGet |
| -------------------------------- | -------------------------------- |
| [Splat.DependencyInjection.SourceGenerator][Core] | [![CoreBadge]][Core] |
[Core]: https://www.nuget.org/packages/Splat.DependencyInjection.SourceGenerator/
[CoreBadge]: https://img.shields.io/nuget/v/Splat.DependencyInjection.SourceGenerator.svg
### Requirements
- .NET SDK: Any version supporting C# 7.3 or later
- Target Frameworks: .NET Framework 4.6.2+, .NET 8+, .NET 9+, .NET 10+
- Splat: Version 19.1.1 or later (supports modern generic-first resolvers)
### Installation
Add the package to your project:
```xml
```
Note: The `PrivateAssets="all"` attribute prevents the source generator from being transitively referenced by projects that depend on yours. This is the recommended configuration for source generators.
## How to Use
### Register Your Dependencies
Use the `SplatRegistrations` static class to register services. The source generator will detect these calls and generate the implementation at compile-time.
**Transient Registration (New Instance Each Time)**
```csharp
using static Splat.SplatRegistrations;
// Register with interface and implementation
Register();
Register();
// Register concrete type only (when no interface)
Register();
```
**Lazy Singleton Registration (Single Lazy Instance)**
```csharp
// Basic lazy singleton
RegisterLazySingleton();
// With thread safety mode
RegisterLazySingleton(LazyThreadSafetyMode.PublicationOnly);
```
Thread safety modes:
- `LazyThreadSafetyMode.ExecutionAndPublication` (default) - Full thread safety with locks
- `LazyThreadSafetyMode.PublicationOnly` - Multiple threads may initialize, first wins
- `LazyThreadSafetyMode.None` - No thread safety (single-threaded scenarios only)
**Constant Registration (Pre-Created Instance)**
```csharp
// Register an existing instance
var config = new Configuration { ApiUrl = "https://api.example.com" };
RegisterConstant(config);
```
**Named Contracts (Multiple Implementations)**
```csharp
// Register multiple implementations with different contracts
Register("file");
Register("console");
Register("cloud");
// Retrieve by contract
var fileLogger = resolver.GetService("file");
```
### Initialize the Container
Call `SetupIOC()` once during application startup in each assembly that uses `SplatRegistrations`:
```csharp
using Splat;
using static Splat.SplatRegistrations;
// In your application entry point
public class App
{
public void ConfigureServices()
{
// Register all dependencies
Register();
Register();
RegisterLazySingleton();
// Initialize the container (generates and executes registrations)
SetupIOC();
}
}
```
For unit tests, pass a custom resolver:
```csharp
[Test]
public void TestDependencies()
{
var resolver = new ModernDependencyResolver();
SetupIOC(resolver); // Use test-specific resolver
var service = resolver.GetService();
Assert.NotNull(service);
}
```
### Constructor Injection
The source generator automatically resolves constructor parameters.
**Single Constructor**
```csharp
public class UserService : IUserService
{
private readonly IDatabase _database;
private readonly ILogger _logger;
// Automatically detected - no attribute needed
public UserService(IDatabase database, ILogger logger)
{
_database = database;
_logger = logger;
}
}
```
**Multiple Constructors**
Use `[DependencyInjectionConstructor]` to specify which constructor to use:
```csharp
using static Splat.SplatRegistrations;
public class AuthService : IAuthService
{
private readonly IDatabase _database;
private readonly ILogger _logger;
// Empty constructor for testing
public AuthService()
{
_database = new InMemoryDatabase();
_logger = new NullLogger();
}
// Production constructor - marked for DI
[DependencyInjectionConstructor]
public AuthService(IDatabase database, ILogger logger)
{
_database = database;
_logger = logger;
}
}
```
If you forget the attribute with multiple constructors, the analyzer will warn you and offer a code fix to add it automatically.
**Lazy Dependencies**
Inject `Lazy` for on-demand initialization:
```csharp
public class ExpensiveService
{
private readonly Lazy _database;
public ExpensiveService(Lazy database)
{
_database = database; // Not initialized yet
}
public void DoWork()
{
// Database initialized only when first accessed
_database.Value.ExecuteQuery("...");
}
}
// Register the dependency as a lazy singleton
RegisterLazySingleton();
Register();
```
### Property Injection
Mark properties with `[DependencyInjectionProperty]` for initialization after construction.
```csharp
using static Splat.SplatRegistrations;
public class ViewModelBase
{
// Property injection - must have public or internal setter
[DependencyInjectionProperty]
public INavigationService Navigation { get; set; }
[DependencyInjectionProperty]
public ILogger Logger { get; internal set; } // Internal setters supported
}
```
The analyzer will:
- Warn if property doesn't have a public/internal setter
- Offer code fix to change `private set` to `public set` or `internal set`
- Offer code fix to add missing setter to read-only properties
### Complete Example
```csharp
using Splat;
using static Splat.SplatRegistrations;
// Models
public interface IDatabase { }
public interface ILogger { }
public interface IUserService { }
public class SqliteDatabase : IDatabase { }
public class FileLogger : ILogger { }
public class UserService : IUserService
{
private readonly IDatabase _database;
// Constructor injection
public UserService(IDatabase database)
{
_database = database;
}
// Property injection
[DependencyInjectionProperty]
public ILogger Logger { get; set; }
}
// Application startup
public class Program
{
public static void Main()
{
// Register dependencies
RegisterLazySingleton();
Register();
Register();
// Initialize container
SetupIOC();
// Resolve services
var userService = Locator.Current.GetService();
}
}
```
## Built-in Analyzers and Code Fixes
The package includes intelligent analyzers that provide real-time feedback:
| Diagnostic ID | Severity | Description | Code Fix |
|--------------|----------|-------------|----------|
| SPLATDI001 | Warning | Multiple constructors without `[DependencyInjectionConstructor]` attribute | Adds attribute to selected constructor |
| SPLATDI002 | Error | Property with `[DependencyInjectionProperty]` lacks accessible setter | Changes setter to `public` or `internal` |
| SPLATDI003 | Error | Multiple constructors marked with `[DependencyInjectionConstructor]` | Manual fix required |
| SPLATDI004 | Error | Constructor marked with `[DependencyInjectionConstructor]` is not accessible | Changes to `public` or `internal` |
The analyzer detects issues in real-time and offers automatic fixes via Quick Actions (Ctrl+. or Cmd+.).
## How It Works
The source generator follows a four-step process:
1. Compile-Time Detection - Scans for `SplatRegistrations.Register()` calls during compilation
2. Metadata Extraction - Analyzes constructor parameters and property injection requirements
3. Code Generation - Generates optimized registration code with no reflection
4. Incremental Builds - Only regenerates when relevant code changes
Generated code example:
```csharp
// Generated by Splat.DependencyInjection.SourceGenerator
static partial void SetupIOCInternal(IDependencyResolver resolver)
{
// Transient registration
resolver.Register(() => new UserService(
(IDatabase)resolver.GetService(typeof(IDatabase)),
(ILogger)resolver.GetService(typeof(ILogger))
) {
Navigation = (INavigationService)resolver.GetService(typeof(INavigationService))
});
// Lazy singleton registration
{
var lazy = new Lazy(() => new SqliteDatabase(),
LazyThreadSafetyMode.ExecutionAndPublication);
resolver.Register>(() => lazy);
resolver.Register(() => lazy.Value);
}
}
```
## Performance Benefits
Compared to reflection-based DI:
- Approximately 100x faster registration execution (no runtime reflection)
- Approximately 10-100x faster incremental builds (only processes changed files)
- Full AOT support (works with Native AOT and trimming)
- Zero runtime overhead (all work done at compile-time)
## Troubleshooting
**Generator doesn't seem to run?**
Ensure you called `SetupIOC()` in your startup code. The generator only produces code for assemblies that use `SplatRegistrations`.
**"Multiple constructors" warning?**
Add `[DependencyInjectionConstructor]` to the constructor you want used. Use the Quick Fix to add automatically.
**Property injection not working?**
Ensure the property has `[DependencyInjectionProperty]` and a `public` or `internal` setter. The analyzer will warn if the setter is missing or inaccessible.
**Lazy dependencies not resolving?**
Make sure you registered the dependency with `RegisterLazySingleton`, not `Register`. Only lazy singletons can be injected as `Lazy`.
## Migration from Version 1.x to 2.x
Version 2.1.1 includes breaking changes:
- Requires Splat 19.1.1 or later for generic-first resolver support
- Migrated from legacy `ISourceGenerator` to modern `IIncrementalGenerator`
- Updated to Roslyn 4.14.0
- Removed support for .NET Standard 2.0 and .NET 6
- Minimum supported frameworks: .NET Framework 4.6.2+, .NET 8+, .NET 9+, .NET 10+
New features in 2.1.1:
- 10-100x faster incremental builds (only processes changed files)
- Cache-friendly pipeline eliminates unnecessary recompilation
- Built-in analyzers with real-time diagnostics and automatic code fixes
- Full Native AOT and trimming support with generic-first API
## Support
If you have questions or need help:
- Check existing [GitHub Issues](https://github.com/reactiveui/Splat.DI.SourceGenerator/issues)
- Ask on [Stack Overflow](https://stackoverflow.com/questions/tagged/splat) with the `splat` tag
- Join our [Slack community](https://reactiveui.net/slack)
Please do not open GitHub issues for general support questions.
## Contribute
We welcome contributions! Here's how you can help:
1. Report Issues: Found a bug? [Open an issue](https://github.com/reactiveui/Splat.DI.SourceGenerator/issues/new)
2. Submit PRs: Improvements are always welcome
3. Documentation: Help improve our examples and docs
4. Testing: Add test cases for edge scenarios
See our [contribution guidelines](CONTRIBUTING.md) for details.
## Sponsorship
The core team members and contributors work on this project in their free time. If Splat.DI.SourceGenerator increases your productivity, please consider supporting the project:
[Become a sponsor](https://github.com/sponsors/reactivemarbles)
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.