Knara.SourceGenerators.DesignPatterns.Singleton 1.1.0

dotnet add package Knara.SourceGenerators.DesignPatterns.Singleton --version 1.1.0
                    
NuGet\Install-Package Knara.SourceGenerators.DesignPatterns.Singleton -Version 1.1.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="Knara.SourceGenerators.DesignPatterns.Singleton" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Knara.SourceGenerators.DesignPatterns.Singleton" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Knara.SourceGenerators.DesignPatterns.Singleton" />
                    
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 Knara.SourceGenerators.DesignPatterns.Singleton --version 1.1.0
                    
#r "nuget: Knara.SourceGenerators.DesignPatterns.Singleton, 1.1.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 Knara.SourceGenerators.DesignPatterns.Singleton@1.1.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=Knara.SourceGenerators.DesignPatterns.Singleton&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Knara.SourceGenerators.DesignPatterns.Singleton&version=1.1.0
                    
Install as a Cake Tool

Singleton Pattern Generator

Build and Test Publish NuGet Packages NuGet NuGet .NET Standard 2.0 Language

A C# source generator that creates thread-safe singleton implementations for .NET Framework applications. Automatically generates correct singleton code and validates thread safety to prevent common concurrency bugs.

Why This Generator Exists

Problem: Manual singleton implementations are error-prone and often contain race conditions that cause intermittent bugs in production. Without dependency injection containers (available in .NET Framework 4.x), singletons are essential for managing shared state.

Solution: Generate proven, thread-safe singleton implementations automatically with built-in validation for common concurrency issues.

Quick Start

  1. Add the source generator to your project:
<ItemGroup> <ProjectReference Include="path/to/Knara.SourceGenerators.DesignPatterns.Singleton.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup>

Or via NuGet (when published):

dotnet add package Knara.SourceGenerators.DesignPatterns.Singleton

If you are using the generator in .net 4.+ projects, refer to this guide for additional steps.

  1. Add the [Singleton] attribute to your partial class
  2. Make sure your class has a private constructor
  3. The generator creates the singleton implementation automatically
using Knara.SourceGenerators.DesignPatterns.Singleton;

[Singleton(Strategy = SingletonStrategy.Lazy)]
public partial class ConfigurationManager
{
    private ConfigurationManager() { } // Private constructor required
    
    public string GetSetting(string key) { /* your code */ }
}

// Usage
var config = ConfigurationManager.Instance;
string setting = config.GetSetting("DatabaseTimeout");

Singleton Strategies

Choose the right strategy based on your use case:

1. Lazy (Default) - SingletonStrategy.Lazy

When to use: Most general-purpose scenarios Performance: Good initialization, good access speed Memory: Minimal overhead

[Singleton(Strategy = SingletonStrategy.Lazy)]
public partial class ConfigurationManager
{
    private readonly ConcurrentDictionary<string, string> _settings = new();
    private ConfigurationManager() { }
}

Best for:

  • Configuration managers
  • Service registries
  • Non-performance-critical singletons

2. Eager - SingletonStrategy.Eager

When to use: When you need the instance ready immediately at startup Performance: Fastest access (no initialization checks) Memory: Instance created at application start

[Singleton(Strategy = SingletonStrategy.Eager)]
public partial class Logger
{
    private readonly string _logFilePath;
    private Logger() 
    {
        _logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "app.log");
    }
}

Best for:

  • Logging systems
  • Critical infrastructure components
  • Components needed immediately at startup

3. LockFree - SingletonStrategy.LockFree

When to use: High-performance scenarios with frequent access Performance: Fastest for read-heavy workloads Memory: Minimal locking overhead

[Singleton(Strategy = SingletonStrategy.LockFree)]
public partial class MetricsCollector
{
    private readonly ConcurrentDictionary<string, long> _counters = new();
    private MetricsCollector() { }
}

Best for:

  • Metrics collection
  • Caching systems
  • High-frequency data access

4. DoubleCheckedLocking - SingletonStrategy.DoubleCheckedLocking

When to use: When you need precise control over initialization timing Performance: Good balance of speed and memory efficiency Memory: Standard locking overhead

[Singleton(Strategy = SingletonStrategy.DoubleCheckedLocking)]
public partial class DbConnectionPool
{
    private readonly ConcurrentQueue<IDbConnection> _connections = new();
    private DbConnectionPool() { }
}

Best for:

  • Database connection pools
  • Resource managers
  • Components with expensive initialization

Thread Safety Validation

The generator automatically checks for common thread safety issues:

❌ Dangerous Collections

[Singleton]
public partial class BadExample
{
    private Dictionary<string, int> _data = new(); // ❌ Will generate warning
    private List<string> _items = new();           // ❌ Will generate warning
}

✅ Thread-Safe Alternatives

[Singleton]
public partial class GoodExample
{
    private ConcurrentDictionary<string, int> _data = new(); // ✅ Thread-safe
    private ConcurrentBag<string> _items = new();            // ✅ Thread-safe
}

Generic Singletons

The generator supports generic singletons with constraints:

[Singleton(Strategy = SingletonStrategy.DoubleCheckedLocking)]
public partial class Repository<T> where T : IEntity
{
    private readonly ConcurrentBag<T> _items = new();
    private Repository() { }
    
    public void Add(T item) => _items.Add(item);
    public IReadOnlyList<T> GetAll() => _items.ToList().AsReadOnly();
}

// Usage
var userRepo = Repository<User>.Instance;
var productRepo = Repository<Product>.Instance;

Initialization Support

Add an Initialize() method for post-construction setup:

[Singleton]
public partial class CacheManager
{
    private CacheManager() { }
    
    private void Initialize()
    {
        // Called automatically after instance creation
        _ = Task.Run(CleanupExpiredEntries);
        Console.WriteLine("Cache cleanup task started");
    }
}

Requirements

  • Partial class: Your class must be declared as partial
  • Private constructor: Required to prevent external instantiation
  • .NET Framework 4.0+: Compatible with legacy applications

Common Patterns

Configuration Management

[Singleton(Strategy = SingletonStrategy.Lazy)]
public partial class AppConfig
{
    private readonly ConcurrentDictionary<string, string> _settings = new();
    private AppConfig() { LoadFromFile(); }
}

Resource Pooling

[Singleton(Strategy = SingletonStrategy.LockFree)]
public partial class ObjectPool<T>
{
    private readonly ConcurrentQueue<T> _objects = new();
    private ObjectPool() { PrePopulatePool(); }
}

Metrics Collection

[Singleton(Strategy = SingletonStrategy.LockFree)]
public partial class PerformanceCounters
{
    private readonly ConcurrentDictionary<string, long> _counters = new();
    private PerformanceCounters() { }
}

Warnings and Diagnostics

The generator provides helpful warnings:

Warning Meaning Solution
Non-thread-safe field Using Dictionary, List, etc. Use ConcurrentDictionary, ConcurrentBag, etc.
Public constructor Constructor is publicly accessible Make constructor private
Class not partial Cannot generate singleton implementation Add partial keyword

Performance Comparison

Strategy Initialization Access Speed Memory Use Case
Lazy Lazy Good Low General purpose
Eager Immediate Fastest Higher Critical systems
LockFree Lazy Fastest Low High-frequency access
DoubleCheckedLocking Lazy Good Low Balanced performance

Best Practices

✅ Do

  • Use ConcurrentDictionary instead of Dictionary
  • Use ConcurrentBag instead of List
  • Make constructors private
  • Use Initialize() method for setup logic
  • Choose appropriate strategy for your use case

❌ Don't

  • Use non-thread-safe collections as instance fields
  • Make constructors public
  • Forget the partial keyword
  • Use singletons for everything (only when truly needed)

Migration from Manual Singletons

Before (error-prone):

public class MyService
{
    private static MyService _instance;
    private static readonly object _lock = new object();
    
    public static MyService Instance 
    {
        get 
        {
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                        _instance = new MyService();
                }
            }
            return _instance;
        }
    }
}

After (generated, correct):

[Singleton]
public partial class MyService
{
    private MyService() { }
    // All singleton logic generated automatically
}

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in 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
1.1.0 127 10/25/2025
1.0.3 160 9/26/2025
1.0.2 198 9/24/2025
1.0.1 193 9/24/2025
1.0.0 196 9/23/2025