BB84.SourceGenerators
1.7.421
See the version list below for details.
dotnet add package BB84.SourceGenerators --version 1.7.421
NuGet\Install-Package BB84.SourceGenerators -Version 1.7.421
<PackageReference Include="BB84.SourceGenerators" Version="1.7.421"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="BB84.SourceGenerators" Version="1.7.421" />
<PackageReference Include="BB84.SourceGenerators"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add BB84.SourceGenerators --version 1.7.421
#r "nuget: BB84.SourceGenerators, 1.7.421"
#:package BB84.SourceGenerators@1.7.421
#addin nuget:?package=BB84.SourceGenerators&version=1.7.421
#tool nuget:?package=BB84.SourceGenerators&version=1.7.421
BB84.SourceGenerators
A collection of C# source generators that automatically generate boilerplate code at compile time, reducing manual coding and improving code maintainability.
Features
This package provides ten powerful source generators:
- Enumerator Extensions Generator - Fast, allocation-free extension methods for enums
- Notification Properties Generator - Automatic INotifyPropertyChanged/INotifyPropertyChanging implementation
- Abstraction Generator - Interface and implementation generation for static classes
- INI File Generator - Compile-time INI file serialization and deserialization
- Builder Generator - Fluent builder pattern generation for classes
- ToString Generator - Compile-time
ToString()override generation - Validator Generator - Compile-time data annotation validation
- Equality Generator - Compile-time
Equals,GetHashCode, and operator generation - Cloneable Generator - Compile-time
Clone()andDeepClone()method generation - Assembly Information Generator - Compile-time assembly metadata constants without reflection
Installation
Install the package via NuGet:
dotnet add package BB84.SourceGenerators
Or via Package Manager Console:
Install-Package BB84.SourceGenerators
Usage
1. Enumerator Extensions Generator
Generates high-performance extension methods for enumerations, providing faster alternatives to Enum.ToString(), Enum.IsDefined(), Enum.GetNames(), and Enum.GetValues().
Attribute
[GenerateEnumeratorExtensions]
Example
using BB84.SourceGenerators.Attributes;
[GenerateEnumeratorExtensions]
public enum Status
{
[System.ComponentModel.Description("Pending approval")]
Pending = 0,
Active = 1,
[System.ComponentModel.Description("Temporarily inactive")]
Inactive = 2,
Deleted = 3
}
Generated Methods
The generator creates the following extension methods:
ToStringFast()- Returns the name of the enum value as a stringIsDefinedFast(this TEnum value)- Checks if an enum value is definedIsDefinedFast(this string name)- Checks if an enum name is definedGetNamesFast()- Returns all enum names as anIEnumerable<string>GetValuesFast()- Returns all enum values as anIEnumerable<TEnum>GetDescriptionFast()- Returns the description from[Description]attribute, or the name if not present
Usage Example
var status = Status.Pending;
// Fast string conversion
string name = status.ToStringFast(); // "Pending"
// Check if defined
bool isDefined = status.IsDefinedFast(); // true
bool isNameDefined = "Active".IsDefinedFast(); // true
// Get description
string description = status.GetDescriptionFast(); // "Pending approval"
// Get all names and values
IEnumerable<string> names = status.GetNamesFast();
IEnumerable<Status> values = status.GetValuesFast();
2. Notification Properties Generator
Automatically generates properties with INotifyPropertyChanged and INotifyPropertyChanging support for private fields in a class.
Attribute
[GenerateNotifications(bool isChanged = false)]
Parameters:
isChanged- Whentrue, generates an additionalIsChangedboolean property that is set totruewhen any property changes
Example
using BB84.SourceGenerators.Attributes;
[GenerateNotifications(isChanged: true)]
public partial class Person
{
private int _id;
private string _name;
private string _email;
private DateTime _createdAt;
private DateTime? _updatedAt;
public Person(int id, string name, string email)
{
_id = id;
_name = name;
_email = email;
_createdAt = DateTime.UtcNow;
}
}
Generated Code
The generator creates:
- Public properties for each private field with change notification
- Implementation of
INotifyPropertyChangedandINotifyPropertyChanginginterfaces PropertyChangedandPropertyChangingeventsRaisePropertyChanged()andRaisePropertyChanging()protected virtual methods- Optional
IsChangedproperty (whenisChangedparameter istrue)
Usage Example
var person = new Person(1, "John Doe", "john@example.com");
// Subscribe to change notifications
person.PropertyChanging += (s, e) => Console.WriteLine($"Property {e.PropertyName} is changing");
person.PropertyChanged += (s, e) => Console.WriteLine($"Property {e.PropertyName} has changed");
// Change a property - events will fire automatically
person.Name = "Jane Doe";
person.Email = "jane@example.com";
// Check if object has been modified (when isChanged: true)
if (person.IsChanged)
{
Console.WriteLine("Person has been modified");
}
3. Abstraction Generator
Generates interface and implementation classes for static classes, making them testable through dependency injection.
Attribute
[GenerateAbstraction(Type targetType, Type abstractionType, Type implementationType, params string[] excludeMethods)]
Parameters:
targetType- The static class to generate an abstraction forabstractionType- The interface type to generateimplementationType- The implementation class type to generateexcludeMethods- Optional array of method names to exclude from generation
Example
using BB84.SourceGenerators.Attributes;
// Generate abstraction for System.IO.File
[GenerateAbstraction(typeof(File), typeof(IFileProvider), typeof(FileProvider))]
public partial class FileProvider
{ }
public partial interface IFileProvider
{ }
Generated Code
The generator creates:
- A complete interface (
IFileProvider) with all public static methods from the target type - An implementation class (
FileProvider) that implements the interface and delegates to the static class - XML documentation comments using
<inheritdoc>
Usage Example
// In your service
public class DocumentService
{
private readonly IFileProvider _fileProvider;
public DocumentService(IFileProvider fileProvider)
=> _fileProvider = fileProvider;
public string ReadDocument(string path)
=> _fileProvider.ReadAllText(path);
}
// In your DI container setup
services.AddSingleton<IFileProvider, FileProvider>();
// In tests, you can mock IFileProvider
var mockFileProvider = new Mock<IFileProvider>();
mockFileProvider.Setup(x => x.ReadAllText(It.IsAny<string>())).Returns("test content");
4. INI File Generator
Generates static Read and Write methods for classes, enabling compile-time INI file serialization and deserialization based on decorated properties.
Attributes
[GenerateIniFile(StringComparison stringComparison = StringComparison.OrdinalIgnoreCase, string sectionDelimiter = ".")]
[GenerateIniFileSection(string? name = null)]
[GenerateIniFileValue(string? name = null)]
Parameters:
GenerateIniFile- Marks a class for INI file code generation. The optionalstringComparisonparameter controls how section and key names are compared during deserialization (default:OrdinalIgnoreCase). The optionalsectionDelimiterparameter specifies the delimiter for nested section names (default:"."). The optionalSerializeCommentsproperty, when set totrue, includes XML documentation<summary>comments from section and value properties as INI comment lines (prefixed with;) in the generatedWriteoutput (default:false)GenerateIniFileSection- Marks a property as an INI file section. The optionalnameparameter specifies the section name; if omitted, the property name is used. Can also be applied to properties within section types to create nested sectionsGenerateIniFileValue- Marks a property as a key-value pair within an INI section. The optionalnameparameter specifies the key name; if omitted, the property name is used
Supported Value Types:
string, int, long, float, double, bool, decimal, DateTime
Example
using BB84.SourceGenerators.Attributes;
[GenerateIniFile]
public partial class AppConfig
{
[GenerateIniFileSection("General")]
public GeneralSection General { get; set; }
[GenerateIniFileSection("Database")]
public DatabaseSection Database { get; set; }
}
public class GeneralSection
{
[GenerateIniFileValue("AppName")]
public string ApplicationName { get; set; }
[GenerateIniFileValue("Version")]
public int ApplicationVersion { get; set; }
[GenerateIniFileValue("Debug")]
public bool IsDebug { get; set; }
}
public class DatabaseSection
{
[GenerateIniFileValue("Server")]
public string Server { get; set; }
[GenerateIniFileValue("Port")]
public int Port { get; set; }
[GenerateIniFileValue("Timeout")]
public double Timeout { get; set; }
}
Generated Methods
The generator creates the following static methods on the decorated class:
Read(string content)- Parses an INI file string and returns a deserialized instanceWrite(TClass instance)- Serializes an instance into an INI file string
Usage Example
// Reading an INI file
string iniContent = File.ReadAllText("config.ini");
AppConfig config = AppConfig.Read(iniContent);
Console.WriteLine(config.General.ApplicationName); // "MyApp"
Console.WriteLine(config.Database.Port); // 5432
// Modifying and writing back
config.General.Debug = false;
config.Database.Timeout = 60.0;
string output = AppConfig.Write(config);
File.WriteAllText("config.ini", output);
Output:
[General]
AppName=MyApp
Version=1
Debug=False
[Database]
Server=localhost
Port=5432
Timeout=60
Case-Sensitive Matching:
By default, section and key names are compared case-insensitively (OrdinalIgnoreCase). To use case-sensitive matching:
[GenerateIniFile(StringComparison.Ordinal)]
public partial class StrictConfig
{
[GenerateIniFileSection("General")]
public GeneralSection General { get; set; }
}
Nested Sections:
The generator supports nested sections by applying [GenerateIniFileSection] to properties within section types. Nested sections are represented with dotted names (e.g., [Server.Database]), and nesting is supported up to 8 levels deep:
[GenerateIniFile]
public partial class Config
{
[GenerateIniFileSection]
public ServerSection Server { get; set; }
}
public class ServerSection
{
[GenerateIniFileValue]
public string Host { get; set; }
[GenerateIniFileSection]
public DatabaseSection Database { get; set; }
}
public class DatabaseSection
{
[GenerateIniFileValue]
public int Port { get; set; }
}
This produces:
[Server]
Host=localhost
[Server.Database]
Port=5432
To use a custom delimiter (e.g., /):
[GenerateIniFile(sectionDelimiter: "/")]
public partial class Config { ... }
// Produces: [Server/Database]
Serializing Comments:
When SerializeComments is set to true, XML documentation <summary> comments on section and value properties are emitted as INI comment lines (prefixed with ; ) in the Write output. The Read method automatically skips these comment lines during deserialization:
[GenerateIniFile(SerializeComments = true)]
public partial class AppConfig
{
/// <summary>
/// General application settings
/// </summary>
[GenerateIniFileSection]
public GeneralSection General { get; set; }
}
public class GeneralSection
{
/// <summary>
/// The display name of the application
/// </summary>
[GenerateIniFileValue]
public string AppName { get; set; }
/// <summary>
/// The current version number
/// </summary>
[GenerateIniFileValue]
public int Version { get; set; }
}
This produces:
; General application settings
[General]
; The display name of the application
AppName=MyApp
; The current version number
Version=1
Enumeration Support:
Regular enums will be serialized as their string name. Enum flags will be serialized as a space-delimited string of individual flag names.
public enum LogLevel { Debug, Info, Warning, Error }
[Flags]
public enum Permissions { None = 0, Read = 1, Write = 2, Execute = 4 }
public class AppSection
{
[GenerateIniFileValue]
public LogLevel Level { get; set; }
[GenerateIniFileValue]
public Permissions Perms { get; set; }
}
This produces:
[App]
Level=Warning
Perms=Read Write Execute
5. Builder Generator
Generates a fluent builder class for classes, providing With{PropertyName}(value) methods for each public settable property and a Build() method that creates the instance.
Attribute
[GenerateBuilder]
Example
using BB84.SourceGenerators.Attributes;
[GenerateBuilder]
public partial class UserProfile
{
public int Id { get; set; }
public string Name { get; set; }
public string? Email { get; set; }
public int Age { get; set; }
public bool IsActive { get; set; }
}
Generated Code
The generator creates a {ClassName}Builder class with:
- A
With{PropertyName}(value)fluent method for each public settable property - A
Build()method that creates the instance via object initializer - Proper nullable reference type annotations
- XML documentation comments
Usage Example
// Create an instance using the fluent builder
UserProfile profile = new UserProfileBuilder()
.WithId(1)
.WithName("John Doe")
.WithEmail("john@example.com")
.WithAge(30)
.WithIsActive(true)
.Build();
// Only set the properties you need - others use default values
UserProfile minimal = new UserProfileBuilder()
.WithName("Jane Doe")
.Build();
// Builders can be reused to create multiple instances
var builder = new UserProfileBuilder()
.WithName("Template User")
.WithIsActive(true);
UserProfile first = builder.WithId(1).Build();
UserProfile second = builder.WithId(2).Build();
6. ToString Generator
Generates a ToString() override for classes, returning a formatted string containing the class name and all (or selected) public readable property values in the format ClassName { Prop1 = val1, Prop2 = val2 }.
Attribute
[GenerateToString(params string[] excludeProperties)]
Parameters:
excludeProperties- Optional list of property names to exclude from the generatedToString()output
Example
using BB84.SourceGenerators.Attributes;
[GenerateToString]
public partial class Product
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public bool InStock { get; set; }
}
// Exclude sensitive or verbose properties
[GenerateToString("PasswordHash", "InternalNotes")]
public partial class User
{
public int Id { get; set; }
public string Name { get; set; }
public string PasswordHash { get; set; }
public string InternalNotes { get; set; }
}
Generated Code
The generator creates a ToString() override on the partial class that:
- Includes all public readable properties by default
- Excludes properties specified in the attribute parameter
- Formats output as
ClassName { Prop1 = val1, Prop2 = val2 } - Returns
ClassName { }when all properties are excluded
Usage Example
var product = new Product
{
Id = 1,
Name = "Widget",
Price = 9.99,
InStock = true
};
Console.WriteLine(product.ToString());
// Output: Product { Id = 1, Name = Widget, Price = 9.99, InStock = True }
var user = new User
{
Id = 42,
Name = "John Doe",
PasswordHash = "abc123hash",
InternalNotes = "VIP customer"
};
Console.WriteLine(user.ToString());
// Output: User { Id = 42, Name = John Doe }
7. Validator Generator
Generates a Validate() method for classes, scanning properties for data annotation attributes at compile time and emitting direct validation checks. This replaces runtime reflection-based Validator.TryValidateObject() with zero-overhead generated code.
Attribute
[GenerateValidator]
Supported Data Annotations:
[Required]- Validates that the property is not null (or not null/empty for strings)[Range(min, max)]- Validates that a numeric value falls within a specified range, or that a collection has between min and max elements[StringLength(max, MinimumLength = min)]- Validates string length within bounds[MinLength(length)]- Validates minimum length of a string or collection[MaxLength(length)]- Validates maximum length of a string or collection[RegularExpression(pattern)]- Validates that a string matches a regex pattern
Example
using System.ComponentModel.DataAnnotations;
using BB84.SourceGenerators.Attributes;
[GenerateValidator]
public partial class UserRegistration
{
[Required]
[StringLength(100, MinimumLength = 2)]
public string? Name { get; set; }
[Required]
[RegularExpression(@"^[^@\s]+@[^@\s]+\.[^@\s]+$")]
public string? Email { get; set; }
[Range(18, 120)]
public int Age { get; set; }
[Required]
[MinLength(8)]
[MaxLength(128)]
public string? Password { get; set; }
[Range(1, 10)]
public List<int>? Skills { get; set; }
}
Generated Code
The generator creates the following methods on the partial class:
Validate()- Returns aDictionary<string, List<string>>where each key is a property name and the value is a list of validation error messages for that property. An empty dictionary indicates a valid instance.Validate(string propertyName)- Returns aList<string>of validation error messages for the specified property. An empty list indicates the property is valid.
Both methods contain direct if-checks for each data annotation rule and support custom error messages via ErrorMessage property.
Usage Example
var registration = new UserRegistration
{
Name = "J",
Email = "not-an-email",
Age = 15,
Password = "short"
};
Dictionary<string, List<string>> errors = registration.Validate();
if (errors.Count > 0)
{
foreach (KeyValuePair<string, List<string>> entry in errors)
{
Console.WriteLine($"{entry.Key}:");
foreach (string error in entry.Value)
{
Console.WriteLine($" - {error}");
}
}
// Output:
// Name:
// - The field Name must be a string with a minimum length of 2 and a maximum length of 100.
// Email:
// - The field Email must match the regular expression '^[^@\s]+@[^@\s]+\.[^@\s]+$'.
// Age:
// - The field Age must be between 18 and 120.
// Password:
// - The field Password must be a string or collection with a minimum length of 8.
}
else
{
Console.WriteLine("Registration is valid!");
}
// Validate a single property
List<string> nameErrors = registration.Validate("Name");
if (nameErrors.Count > 0)
{
Console.WriteLine($"Name errors: {string.Join(", ", nameErrors)}");
}
// Custom error messages
[GenerateValidator]
public partial class LoginModel
{
[Required(ErrorMessage = "Username is required.")]
public string? Username { get; set; }
[Required(ErrorMessage = "Password cannot be empty.")]
[MinLength(6, ErrorMessage = "Password must be at least 6 characters.")]
public string? Password { get; set; }
}
8. Equality Generator
Generates Equals(object), Equals(T), GetHashCode(), operator ==, and operator != for classes, implementing IEquatable<T>. This replaces tedious and error-prone manual equality implementations with zero-overhead generated code.
Attribute
[GenerateEquality(params string[] excludeProperties)]
Parameters:
excludeProperties- Optional list of property names to exclude from the generated equality comparison
Example
using BB84.SourceGenerators.Attributes;
[GenerateEquality]
public partial class Product
{
public int Id { get; set; }
public string? Name { get; set; }
public double Price { get; set; }
public bool InStock { get; set; }
}
// Exclude volatile or non-significant properties
[GenerateEquality("CachedHash", "LastAccessed")]
public partial class User
{
public int Id { get; set; }
public string? Name { get; set; }
public string? CachedHash { get; set; }
public DateTime LastAccessed { get; set; }
}
Generated Code
The generator creates the following members on the partial class:
Equals(object?)override — delegates to the typedEquals(T?)methodEquals(T?)implementingIEquatable<T>— compares all (or selected) public propertiesGetHashCode()override — produces a consistent hash from all (or selected) public propertiesoperator ==andoperator !=— delegates toEquals
Usage Example
var a = new Product { Id = 1, Name = "Widget", Price = 9.99, InStock = true };
var b = new Product { Id = 1, Name = "Widget", Price = 9.99, InStock = true };
var c = new Product { Id = 2, Name = "Gadget", Price = 19.99, InStock = false };
// Typed equality
bool equal = a.Equals(b); // true
bool different = a.Equals(c); // false
// Operator equality
bool op = a == b; // true
bool neq = a != c; // true
// Consistent hash codes
bool sameHash = a.GetHashCode() == b.GetHashCode(); // true
// Works with collections that use equality
var set = new HashSet<Product> { a };
bool contains = set.Contains(b); // true
// IEquatable<T> is implemented
IEquatable<Product> equatable = a;
9. Cloneable Generator
Generates Clone() and DeepClone() methods for classes, implementing ICloneable. The Clone() method performs a shallow copy, while DeepClone() recursively deep clones reference-type properties that are also marked with [GenerateCloneable].
Attribute
[GenerateCloneable(params string[] excludeProperties)]
Parameters:
excludeProperties- Optional list of property names to exclude from the generated clone methods
Example
using BB84.SourceGenerators.Attributes;
[GenerateCloneable]
public partial class UserProfile
{
public int Id { get; set; }
public string? Name { get; set; }
public double Score { get; set; }
public Address? Address { get; set; }
}
[GenerateCloneable]
public partial class Address
{
public string? Street { get; set; }
public string? City { get; set; }
}
// Exclude specific properties from cloning
[GenerateCloneable("CacheToken")]
public partial class Session
{
public int Id { get; set; }
public string? User { get; set; }
public string? CacheToken { get; set; }
}
Generated Code
The generator creates the following members on the partial class:
Clone()— creates a shallow copy by assigning all included public read/write propertiesDeepClone()— creates a deep copy; reference-type properties marked with[GenerateCloneable]are recursively deep cloned, while other properties are shallow copied- Explicit
ICloneable.Clone()— delegates toDeepClone()
Usage Example
var original = new UserProfile
{
Id = 1,
Name = "John Doe",
Score = 95.5,
Address = new Address { Street = "123 Main St", City = "Springfield" }
};
// Shallow clone - Address is the same reference
UserProfile shallow = original.Clone();
shallow.Address.City = "Shelbyville";
Console.WriteLine(original.Address.City); // "Shelbyville" (shared reference)
// Deep clone - Address is a new independent instance
UserProfile deep = original.DeepClone();
deep.Address.City = "Capital City";
Console.WriteLine(original.Address.City); // "Shelbyville" (unaffected)
// ICloneable is implemented (delegates to DeepClone)
ICloneable cloneable = original;
object copy = cloneable.Clone();
// Excluded properties are not copied
var session = new Session { Id = 1, User = "admin", CacheToken = "abc123" };
Session clonedSession = session.Clone();
Console.WriteLine(clonedSession.CacheToken); // null
10. Assembly Information Generator
Generates compile-time constant properties for assembly metadata (title, version, company, copyright, etc.), eliminating the need for runtime reflection via Assembly.GetCustomAttribute<T>().
Attribute
[GenerateAssemblyInformation]
Example
using BB84.SourceGenerators.Attributes;
[GenerateAssemblyInformation]
public partial class AppInfo
{ }
Generated Code
The generator creates public const string properties for each standard assembly attribute:
Title— fromAssemblyTitleAttributeDescription— fromAssemblyDescriptionAttributeCompany— fromAssemblyCompanyAttributeProduct— fromAssemblyProductAttributeCopyright— fromAssemblyCopyrightAttributeTrademark— fromAssemblyTrademarkAttributeConfiguration— fromAssemblyConfigurationAttributeVersion— fromAssemblyVersionAttributeFileVersion— fromAssemblyFileVersionAttributeInformationalVersion— fromAssemblyInformationalVersionAttribute
Usage Example
Console.WriteLine(AppInfo.Title); // "MyApp"
Console.WriteLine(AppInfo.Version); // "1.0.0.0"
Console.WriteLine(AppInfo.Company); // "My Company"
Console.WriteLine(AppInfo.Copyright); // "Copyright © 2025"
Console.WriteLine(AppInfo.InformationalVersion); // "1.0.0+abc123"
Requirements
- .NET Standard 2.0 or higher
- C# 7.3 or higher
- Supports .NET Framework 4.7.2+, .NET Core 2.0+, .NET 5+, .NET 6+, .NET 7+, .NET 8+
Performance Benefits
Enum Extensions
The generated enum extension methods provide significant performance improvements over reflection-based Enum methods:
- ToStringFast() - Avoids boxing and uses switch expressions
- IsDefinedFast() - Compile-time switch instead of runtime reflection
- GetNamesFast()/GetValuesFast() - Returns pre-allocated arrays instead of reflection
Notification Properties
- Generates optimized property setters with inline equality checks
- Avoids reflection overhead of PropertyChanged.Fody or similar tools
- Compile-time code generation means zero runtime overhead
INI File Serialization
- Generates direct string parsing and formatting code at compile time
- Avoids runtime reflection or third-party INI parsing libraries
- Uses
CultureInfo.InvariantCulturefor consistent cross-platform formatting
Builder Pattern
- Generates a complete fluent builder class at compile time
- Eliminates hand-written builder boilerplate that must be kept in sync with the target class
- Replaces reflection-based or expression-tree-based builder libraries with zero-overhead generated code
- Full nullable reference type support for type-safe builder APIs
ToString Generation
- Generates a direct property-formatting
ToString()override at compile time - Replaces runtime reflection approaches (
typeof(T).GetProperties().Select(...)) with zero-overhead generated code - Automatically stays in sync with the class definition - no manual maintenance required
- Supports property exclusion for sensitive or verbose fields
Validation
- Generates direct
if-checks at compile time for each data annotation rule - Replaces
Validator.TryValidateObject()which usesTypeDescriptorand reflection at runtime - Provides compile-time discovery of validation attributes - no runtime attribute scanning
- Supports custom error messages for localization and user-friendly feedback
Equality
- Generates correct
Equals,GetHashCode,==, and!=implementations at compile time - Eliminates tedious and error-prone manual equality boilerplate
- Replaces runtime reflection approaches with zero-overhead generated code
- Properly handles null references and value type properties
- Supports property exclusion for volatile or non-significant fields
Cloneable
- Generates
Clone()andDeepClone()methods at compile time with zero runtime overhead - Replaces
MemberwiseClone(shallow only), serialization round-trips (slow), and manual clone implementations (error-prone) - Recursively deep clones reference-type properties marked with
[GenerateCloneable] - Implements
ICloneablefor framework compatibility - Supports property exclusion for transient or computed fields
Assembly Information
- Generates
const stringproperties at compile time for all standard assembly attributes - Eliminates runtime reflection via
Assembly.GetCustomAttribute<T>() - Constants can be used in attribute arguments, switch expressions, and other compile-time contexts
- Automatically stays in sync with project file properties (
<AssemblyTitle>,<Version>, etc.)
How It Works
Source generators run during compilation and generate additional C# source files that are compiled alongside your code. This means:
- Zero runtime overhead - All code is generated at compile time
- IntelliSense support - Generated code appears in Visual Studio IntelliSense
- Debuggable - You can step through generated code during debugging
- No reflection - Generated code uses direct method calls
Contributing
Contributions are welcome! Please feel free to submit a Pull Request but see the Conduct first.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Robert Peter Meyer (BoBoBaSs84)
- GitHub: @BoBoBaSs84
- Repository: BB84.SourceGenerators
Changelog
See releases for version history and changelog.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
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 |
|---|---|---|
| 2.2.614 | 220 | 6/14/2026 |
| 2.1.607 | 237 | 6/7/2026 |
| 2.0.529 | 165 | 5/29/2026 |
| 2.0.526 | 169 | 5/26/2026 |
| 2.0.524 | 123 | 5/24/2026 |
| 1.11.515 | 163 | 5/15/2026 |
| 1.10.507 | 155 | 5/7/2026 |
| 1.9.503 | 153 | 5/3/2026 |
| 1.9.430 | 128 | 4/30/2026 |
| 1.9.428 | 122 | 4/28/2026 |
| 1.8.426 | 141 | 4/26/2026 |
| 1.7.421 | 131 | 4/21/2026 |
| 1.6.419 | 121 | 4/19/2026 |
| 1.5.417 | 110 | 4/17/2026 |
| 1.4.416 | 109 | 4/16/2026 |
| 1.4.415 | 112 | 4/15/2026 |
| 1.3.413 | 128 | 4/13/2026 |
| 1.3.412 | 119 | 4/12/2026 |
| 1.2.410 | 130 | 4/10/2026 |
| 1.2.409.1 | 108 | 4/9/2026 |