Generate Manifests Automatically
Learn how to use source generators to automatically create domain manifests from your entity classes without manual string writing.
Overview
The JD.Domain.ManifestGeneration.Generator source generator automatically analyzes your entity classes at compile-time and generates DomainManifest instances based on your code structure and data annotations.
Key Benefits:
- ✅ No manual string writing - Metadata extracted automatically from your code
- ✅ Compile-time generation - No runtime reflection overhead
- ✅ Type-safe - Uses actual class and property names from code
- ✅ Respects sources of truth - Entity classes, data annotations, and fluent configurations
- ✅ Opt-in - Explicit attributes required, no magic discovery
Prerequisites
Install the required packages:
# Attributes (referenced by your code)
dotnet add package JD.Domain.ManifestGeneration
# Source generator (private assets, analyzer)
dotnet add package JD.Domain.ManifestGeneration.Generator
Basic Usage
1. Mark Your Entities
Add attributes to your entity classes:
using System.ComponentModel.DataAnnotations;
using JD.Domain.ManifestGeneration;
// Assembly-level manifest configuration
[assembly: GenerateManifest("ECommerce", Version = "1.0.0")]
namespace MyApp.Domain;
[DomainEntity(TableName = "Customers", Schema = "dbo")]
public class Customer
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(200)]
public string Name { get; set; } = string.Empty;
[Required]
[EmailAddress]
[MaxLength(500)]
public string Email { get; set; } = string.Empty;
public DateTime? DateOfBirth { get; set; }
// Opt-out specific properties
[ExcludeFromManifest]
public DateTime InternalTimestamp { get; set; }
}
[DomainValueObject]
public class Address
{
[Required]
[MaxLength(200)]
public string Street { get; set; } = string.Empty;
[Required]
[MaxLength(100)]
public string City { get; set; } = string.Empty;
}
2. Build Your Project
The generator runs automatically at build time:
dotnet build
3. Use the Generated Manifest
The generator creates a static class with your manifest:
using MyApp.Domain;
// Access the auto-generated manifest
var manifest = ECommerceManifest.GeneratedManifest;
Console.WriteLine($"Domain: {manifest.Name}");
Console.WriteLine($"Version: {manifest.Version}");
Console.WriteLine($"Entities: {manifest.Entities.Count}");
Console.WriteLine($"Value Objects: {manifest.ValueObjects.Count}");
Configuration Options
Assembly-Level Attribute
Configure manifest generation for the entire assembly:
[assembly: GenerateManifest(
"MyDomain", // Manifest name (required)
Version = "1.0.0", // Version string
Namespace = "MyApp.Generated", // Custom namespace (default: JD.Domain.Generated)
OutputPath = "manifest.json" // Optional JSON output (future feature)
)]
Entity Attribute
Configure entity-specific settings:
[DomainEntity(
TableName = "tbl_Customers", // Database table name
Schema = "sales", // Database schema
Description = "Customer entity" // Documentation
)]
public class Customer { }
Value Object Attribute
Mark classes as value objects:
[DomainValueObject(
Description = "Postal address" // Documentation
)]
public class Address { }
Exclusion Attribute
Exclude specific classes or properties:
[DomainEntity]
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
// Property excluded from manifest
[ExcludeFromManifest]
public byte[] InternalData { get; set; }
}
// Entire class excluded
[ExcludeFromManifest]
public class InternalAuditLog { }
Supported Data Annotations
The generator automatically extracts metadata from standard data annotations:
| Attribute | Extracted Metadata |
|---|---|
[Key] |
Marks property as primary key |
[Required] |
Sets IsRequired = true |
[MaxLength(n)] |
Sets MaxLength = n |
Nullable reference types (string?) |
Sets IsRequired = false |
Non-nullable value types (int, DateTime) |
Sets IsRequired = true |
Advanced Scenarios
Multiple Entities
Mark multiple entities in the same assembly:
[assembly: GenerateManifest("ECommerce", Version = "1.0.0")]
[DomainEntity]
public class Customer { }
[DomainEntity]
public class Order { }
[DomainEntity]
public class Product { }
All entities are included in a single manifest.
Custom Namespaces
Generate manifests in a specific namespace:
[assembly: GenerateManifest(
"MyDomain",
Version = "1.0.0",
Namespace = "MyCompany.MyApp.Manifests"
)]
The generated class will be in MyCompany.MyApp.Manifests.MyDomainManifest.
Combining with Rules
Auto-generated manifests can be extended with rules:
// Manifest generated automatically from entities
var baseManifest = ECommerceManifest.GeneratedManifest;
// Add business rules manually
var customerRules = new RuleSetBuilder<Customer>("Default")
.Invariant("Email.Valid", c => IsValidEmail(c.Email))
.WithMessage("Email must be valid")
.Build();
// Create extended manifest
var extendedManifest = new DomainManifest
{
Name = baseManifest.Name,
Version = baseManifest.Version,
Entities = baseManifest.Entities,
ValueObjects = baseManifest.ValueObjects,
Enums = baseManifest.Enums,
Configurations = baseManifest.Configurations,
Sources = baseManifest.Sources,
Metadata = baseManifest.Metadata,
RuleSets = new List<RuleSetManifest> { customerRules }
};
Troubleshooting
Generator Not Running
Problem: No manifest code is generated after build.
Solutions:
Ensure you have both packages installed:
JD.Domain.ManifestGenerationJD.Domain.ManifestGeneration.Generator
If you're referencing the generator project directly, ensure the reference is marked as an analyzer:
<ProjectReference Include="..\..\src\JD.Domain.ManifestGeneration.Generator\JD.Domain.ManifestGeneration.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />Clean and rebuild:
dotnet clean dotnet build
Missing Entities
Problem: Some entities are not included in the generated manifest.
Solutions:
- Ensure the class has the
[DomainEntity]or[DomainValueObject]attribute - Check that the class is not marked with
[ExcludeFromManifest] - Verify the
[assembly: GenerateManifest(...)]attribute is present - Ensure the class is
public
Property Not Extracted
Problem: A property is missing from the generated manifest.
Possible Causes:
- Property is marked with
[ExcludeFromManifest] - Property is not
public - Property is
static
Next Steps
- Use Generated Manifests with EF Core
- Generate Domain Types from Manifests
- Generate FluentValidation Validators
- Create Snapshots for Version Management