Feature Catalog
This is the complete catalog of code-generating pipelines in Pragmatic Design: the ~21 feature pipelines inside the unified Pragmatic.SourceGenerator, the inline Manifest generator, and the three standalone generators that ship with their own modules.
Each entry lists the trigger (the attribute or marker that activates it) and a short sketch of the generated output. Triggers are quoted from FeatureDetector.cs / AttributeNames.cs; where the exact output is large, it is summarised rather than reproduced.
Unified generator — feature pipelines
Section titled “Unified generator — feature pipelines”Actions
Section titled “Actions”Trigger: [DomainAction] / [Action] / [Query] / [EventHandler] (Pragmatic.Actions.Attributes.*) on a partial class.
Generates: a typed invoker (validation → authorization → handler dispatch) nested in the action’s partial class, a SetDependencies injection point, and centralized DI registration (_Infra.Actions.Registration.g.cs).
[DomainAction]public partial class PlaceOrder : IDomainAction<OrderResult> { /* Handle(...) */ }// → partial class PlaceOrder { internal sealed class Invoker { ... } } + DI registrationEndpoints
Section titled “Endpoints”Trigger: [Endpoint] / [ExposeEndpoint<T>] / [Get] [Post] [Put] [Delete] (Pragmatic.Endpoints.Attributes.*).
Generates: minimal-API endpoint registrations bound to the matching action/query, with route, verb, and parameter binding. Also invokes the Manifest generator inline.
Persistence (orchestrator → 6 sub-features)
Section titled “Persistence (orchestrator → 6 sub-features)”Trigger: [Query<TEntity, TResult>] (runtime HasPersistence) and [PragmaticDbContext] (HasPersistenceEFCore).
PersistenceFeature is a thin orchestrator delegating to six sub-features:
| Sub-feature | Generates |
|---|---|
| EntityCore | entity trait properties (PersistenceId, Id, audit, soft-delete), Create(...) factories, relation setters |
| Repository | per-entity repositories, query filters, metadata |
| Query | Query/GridFilter/FilterDto + Apply() projection bodies |
| Projection | [Projectable], computed filters, DTO include expressions |
| Advanced | inheritance, hierarchy, timeline, lookup |
| DbContext | BoundaryDbContext, MigrationDbContext, host-level EntityConfig.* |
Provider-specific SQL is selected via the detected EfCoreProvider (PostgreSQL / SQL Server / SQLite / Generic).
Validation
Section titled “Validation”Trigger: [Validation] / [Validator] (Pragmatic.Validation.Attributes.*).
Generates: compiled validators and the validation pass invoked by the action invoker — no expression-tree or reflection cost at runtime.
Mapping
Section titled “Mapping”Trigger: [MapFrom<TSource>] / [MapTo<T>] (Pragmatic.Mapping.Attributes.MapFromAttribute`1).
Generates: FromEntity / ToEntity mapping methods on the annotated DTO partial; [MapIgnore] excludes members.
[MapFrom<User>]public partial class UserDto { public string Name { get; set; } }// → partial class UserDto { public static UserDto FromEntity(User e) => ...; }Caching
Section titled “Caching”Trigger: [Cacheable] / [CacheKey] / [InvalidatesCache] (Pragmatic.Caching.Attributes.*).
Generates: caching decorators around actions/queries, deterministic cache-key builders, and invalidation hooks.
Trigger: [GeneratePatch<T>] (Pragmatic.Patch.Attributes.GeneratePatchAttribute`1).
Generates: a patch DTO of Optional<T> fields plus an ApplyTo(target) method that only writes the members that were explicitly set (JSON-merge / PATCH semantics).
Composition
Section titled “Composition”Trigger: Composition assembly reference (detected by CompositionDetector); host mode adds an executable entry point + Pragmatic.Composition.Host reference.
Generates (host mode): the aggregated PragmaticHost.Services.g.cs DI wiring, endpoint route groups, and RemoteBoundary HTTP invokers/dispatcher for distributed boundaries. This is where most cross-feature aggregation lands. Emits the bulk of the PRAG16xx diagnostics.
Configuration
Section titled “Configuration”Trigger: [Configuration] (Pragmatic.Configuration.ConfigurationAttribute).
Generates: strongly-typed options binding + registration for a configuration section, with validation diagnostics (PRAG2000, PRAG2001, PRAG2050).
Identity
Section titled “Identity”Trigger: [PragmaticUser] / [ProfileProperty] (Pragmatic.Identity.*); persistence variant via HasIdentityPersistence.
Generates: ToProfile() + profile record, claim→entity user resolvers, and permission constants/registry from IPermission/IRole.
Messaging
Section titled “Messaging”Trigger: [MessageHandler] (Pragmatic.Messaging.Attributes.MessageHandlerAttribute) and related saga/outbox attributes.
Generates: handler pipelines (with [Retry]/[Timeout] middleware), message-type registry, outbox source, topology + routing registries, and saga orchestrators. Diagnostics PRAG0800-0831.
Trigger: [assembly: TranslationKeys] (Pragmatic.Internationalization.Attributes.TranslationKeysAttribute) + .json translation AdditionalFiles.
Generates: strongly-typed translation-key accessors from the resource files, validated against the configured keys (PRAG1800-1803).
Result (feature pipeline)
Section titled “Result (feature pipeline)”Trigger: Pragmatic.Result.IError present (HasResult).
Within the unified generator this drives Result-aware composition in other features. The actual Result/VoidResult type variants are emitted by the standalone ResultSourceGenerator (below).
Resource
Section titled “Resource”Trigger: [Resource] (Pragmatic.Persistence.Entity.ResourceAttribute) on an entity class.
Generates: from a kebab-case route segment + Capabilities flags (Create/Read/Update/Delete/List/Search), the full CRUD surface — Create/Read/Update/Delete actions, List/Search query classes, the matching DTOs, and REST endpoints. The action/query/endpoint models are injected into the Actions/Query/Endpoints pipelines rather than emitted standalone. Diagnostics PRAG2602-2605.
Traits
Section titled “Traits”Trigger: [HasComments], [HasTags], [HasNotes<T>], [HasAttachments] (Pragmatic.Comments / Pragmatic.Tags / Pragmatic.Notes / Pragmatic.Attachments) on an entity.
Generates: a complete sub-feature per trait — the child entity (e.g. OrderComment), its EF EntityConfig, the parent navigation property, CRUD action classes, permission constants, a DTO, a paged list query, and (when a [Resource] is present) REST endpoints. Tags additionally generate a junction entity. Requires HasPersistenceEFCore; actions/endpoints require HasActions. Diagnostics PRAG2600-2601.
[Resource("comments")][HasComments]public partial class Article { ... }// → ArticleComment entity + config + nav, Add/GetById/Update/Delete actions,// ArticleCommentDto, ListArticleCommentsQuery, permissions, endpointsFastEnum (registered unconditionally)
Section titled “FastEnum (registered unconditionally)”Trigger: [FastEnum] (Pragmatic.FastEnumAttribute) on an enum.
Generates: a {Enum}Extensions static class with zero-reflection helpers — ToStringFast(), IsDefined(value) / IsDefined(string), TryParse(...) (+ case-insensitive overload), GetValues(), GetNames(), Count — plus a separate AOT-safe {Enum}JsonConverter (serializes as the string name). Optional GetDisplayName() (from [Display]/[Description]) and, when I18n is referenced, GetI18nKey() / GetLocalizedName().
[FastEnum] public enum Status { Active, Archived }// → public static class StatusExtensions { ToStringFast, IsDefined, TryParse, GetValues, GetNames, Count }// public sealed class StatusJsonConverter : JsonConverter<Status>Jobs (registered unconditionally)
Section titled “Jobs (registered unconditionally)”Trigger: [Job] / [RecurringJob] (+ [Retry], [Timeout], [ContinueWith<T>]) on a partial IJob/IJob<T>.
Generates: a typed job invoker, a job-type registry, recurring-job registration (cron-validated), and DI/metadata. Diagnostics PRAG2500-2506.
ValueObject (registered unconditionally)
Section titled “ValueObject (registered unconditionally)”Trigger: [ValueObject] (Pragmatic.Persistence.Entity.ValueObjectAttribute) on a partial record.
Generates: factory methods into the record — Create(...) (calls the user’s Validate(...), returning the value object or a validation error) when a Validate method exists, and CreateUnsafe(...) (direct construction, for deserialization / trusted paths) when a constructor exists. Neither is emitted if the user already declared it. Diagnostics PRAG2700-2702.
[ValueObject]public partial record Email(string Value){ public static Result<Email, ValidationError> Validate(string value) => ...;}// → public static Result<Email, ValidationError> Create(string value) => Validate(value);// public static Email CreateUnsafe(string value) => new Email(value);Manifest (inline, via EndpointsFeature)
Section titled “Manifest (inline, via EndpointsFeature)”Trigger: runs from EndpointsFeature when endpoint models exist (not a standalone [Generator]).
Generates: a unified compile-time API manifest (JSON) aggregating endpoint + DTO metadata. Feeds OpenAPI enrichment, CLI client generation, and the WASM client generator. Generation failure surfaces as PRAG9001 (Warning) without breaking the build.
Standalone generators
Section titled “Standalone generators”These are separate [Generator] assemblies, not feature pipelines inside the unified generator.
Result — ResultSourceGenerator + ErrorLocalizationGenerator
Section titled “Result — ResultSourceGenerator + ErrorLocalizationGenerator”Assembly: Pragmatic.Result.SourceGenerator.
ResultSourceGeneratorruns only while compiling thePragmatic.Resultassembly itself. It emits the multi-errorResultvariantsResult3–Result9(2–8 error types) andVoidResult<E1,E2>–VoidResult<E1..E8>— theMatch/Map/Bindarity overloads the library ships.ErrorLocalizationGeneratortargets anypartialtype implementingPragmatic.Result.IError. It generates convention-basedTitleKey/DescriptionKeyproperties ({namespace}.{class-without-Error}.{title|description}, lowercased), and skips types that already declare those keys.
public partial class NotFoundError : IError { }// in MyApp.Errors → TitleKey = "myapp.errors.notfound.title", DescriptionKey = "...description"Internationalization — Country / Currency / Language code generators
Section titled “Internationalization — Country / Currency / Language code generators”Assembly: Pragmatic.Internationalization.SourceGenerator.
Three generators that emit static ISO code tables from embedded JSON resources. Each is gated by an AdditionalFiles marker file (empty file with a magic name):
| Generator | Marker file | Output |
|---|---|---|
CountryCodeGenerator | .generate-countries | static CountryCode properties (ISO 3166-1) |
CurrencyCodeGenerator | .generate-currencies | static CurrencyCode properties (ISO 4217) |
LanguageCodeGenerator | .generate-languages | static LanguageCode properties (ISO 639) |
Without the marker file, the generator stays silent — so apps pay nothing unless they opt in.
Logging — LoggingSourceGenerator
Section titled “Logging — LoggingSourceGenerator”Assembly: Pragmatic.Logging.SourceGenerator.
Trigger: [LoggerMethod] (Pragmatic.Logging.Attributes.LoggerMethodAttribute) on a partial method.
Generates: zero-allocation partial method bodies (one generated file per containing type, grouping all of that type’s logger methods), in the spirit of [LoggerMessage] but tailored to the Pragmatic logging contract.
public partial class OrderService{ [LoggerMethod(Level = LogLevel.Information, Message = "Order {OrderId} placed")] public partial void OrderPlaced(Guid orderId);}// → generated partial method body, no boxing / no string.Format on the hot pathSee also
Section titled “See also”- How it works — the detect → transform → template → emit pipeline.
- Feature detection — marker types and the
DetectedFeaturesflags. - Diagnostics — the full
PRAGID reference.