Skip to main content

Overview

Template registrations define how templates are instantiated and registered with the Intent Architect Software Factory. They determine which models trigger template instantiation and how template instances are created.

Base Classes

TemplateRegistrationBase

The abstract base class for all template registrations.
public abstract class TemplateRegistrationBase : ITemplateRegistration
{
    public abstract string TemplateId { get; }
    protected abstract void Register(ITemplateInstanceRegistry registry, IApplication application);
}
TemplateId
string
Unique identifier for the template. Must match the template’s ID.

Registration Patterns

FilePerModelTemplateRegistration<TModel>

Creates one template instance for each model returned by GetModels().

Abstract Members

CreateTemplateInstance
(IOutputTarget, TModel) => ITemplate
required
Factory method that creates a template instance for each model.
GetModels
(IApplication) => IEnumerable<TModel>
required
Returns the models that should each create a template instance.

Example

public class EntityTemplateRegistration : FilePerModelTemplateRegistration<ClassModel>
{
    private readonly IMetadataManager _metadataManager;

    public EntityTemplateRegistration(IMetadataManager metadataManager)
    {
        _metadataManager = metadataManager;
    }

    public override string TemplateId => EntityTemplate.TemplateId;

    public override ITemplate CreateTemplateInstance(IOutputTarget outputTarget, ClassModel model)
    {
        return new EntityTemplate(outputTarget, model);
    }

    public override IEnumerable<ClassModel> GetModels(IApplication application)
    {
        return _metadataManager.Domain(application).GetClassModels()
            .Where(x => x.HasStereotype("Entity"));
    }
}

SingleFileListModelTemplateRegistration<TModel>

Creates a single template instance that receives a list of models.

Abstract Members

CreateTemplateInstance
(IOutputTarget, IEnumerable<TModel>) => ITemplate
required
Factory method that creates a single template instance with all models.
GetModels
(IApplication) => IEnumerable<TModel>
required
Returns the models to pass to the template instance.

Example

public class DependencyInjectionRegistration : SingleFileListModelTemplateRegistration<ClassModel>
{
    private readonly IMetadataManager _metadataManager;

    public DependencyInjectionRegistration(IMetadataManager metadataManager)
    {
        _metadataManager = metadataManager;
    }

    public override string TemplateId => DependencyInjectionTemplate.TemplateId;

    public override ITemplate CreateTemplateInstance(
        IOutputTarget outputTarget, 
        IEnumerable<ClassModel> models)
    {
        return new DependencyInjectionTemplate(outputTarget, models);
    }

    public override IEnumerable<ClassModel> GetModels(IApplication application)
    {
        return _metadataManager.Services(application).GetServiceModels();
    }
}

StaticContentTemplateRegistration

Registers static content files from a module’s content folder for inclusion in the output.

Properties

ContentSubFolder
string
Subfolder within the module’s content folder. Default is "/".
RelativeOutputPathPrefix
string
Prefix added to the relative output path. Default is empty.
BinaryFileGlobbingPatterns
string[]
Glob patterns identifying binary files (e.g., ["**/*.png", "**/*.jpg"]).

Methods

Replacements
(IOutputTarget) => IReadOnlyDictionary<string, string>
Returns key-value pairs for token replacement in static content files.

Example

public class SolutionItemsTemplateRegistration : StaticContentTemplateRegistration
{
    public const string TemplateId = "MyModule.SolutionItems";

    public SolutionItemsTemplateRegistration() : base(TemplateId)
    {
    }

    public override string TemplateId => TemplateId;

    public override string ContentSubFolder => "SolutionItems";

    public override string RelativeOutputPathPrefix => "solution-items";

    public override string[] BinaryFileGlobbingPatterns => new[]
    {
        "**/*.png",
        "**/*.jpg"
    };

    public override IReadOnlyDictionary<string, string> Replacements(IOutputTarget outputTarget)
    {
        return new Dictionary<string, string>
        {
            ["ProjectName"] = outputTarget.ApplicationName()
        };
    }
}
Token Replacement: In your static content files, use tokens in the format <#= {TokenName} #> which will be replaced with the corresponding value:
{
  "name": "<#= ProjectName #>",
  "version": "1.0.0"
}

Custom Registration

For advanced scenarios, implement TemplateRegistrationBase directly.
public class CustomTemplateRegistration : TemplateRegistrationBase
{
    public override string TemplateId => CustomTemplate.TemplateId;

    protected override void Register(ITemplateInstanceRegistry registry, IApplication application)
    {
        // Custom registration logic
        registry.RegisterTemplate(
            TemplateId,
            outputTarget => new CustomTemplate(outputTarget));

        // Can register multiple instances
        for (int i = 0; i < 5; i++)
        {
            registry.RegisterTemplate(
                TemplateId,
                outputTarget => new CustomTemplate(outputTarget, i));
        }
    }
}

ITemplateInstanceRegistry

The registry interface used to register template instances.

Methods

RegisterTemplate

void RegisterTemplate(string templateId, Func<IOutputTarget, ITemplate> createTemplateInstance)
Registers a template instance factory.
templateId
string
required
The template identifier.
createTemplateInstance
Func<IOutputTarget, ITemplate>
required
Factory function that creates the template instance.

RegisterTemplateForModel

void RegisterTemplateForModel<TModel>(
    string templateId, 
    TModel model, 
    Func<IOutputTarget, ITemplate> createTemplateInstance)
Registers a template instance bound to a specific model.
templateId
string
required
The template identifier.
model
TModel
required
The model this template instance is bound to.
createTemplateInstance
Func<IOutputTarget, ITemplate>
required
Factory function that creates the template instance.

Decorator Registration

Decorators extend templates with additional functionality. See the decorator pattern documentation for more details.

DecoratorRegistration<TTemplate, TDecoratorContract>

public abstract class DecoratorRegistration<TTemplate, TDecoratorContract> : IDecoratorRegistration
    where TTemplate : IHasDecorators<TDecoratorContract>
    where TDecoratorContract : ITemplateDecorator
{
    public abstract string DecoratorId { get; }
    public abstract TDecoratorContract CreateDecoratorInstance(TTemplate template, IApplication application);
}
DecoratorId
string
Unique identifier for the decorator.
CreateDecoratorInstance
(TTemplate, IApplication) => TDecoratorContract
required
Factory method that creates the decorator instance.

Example

public class EntityAuditFieldsDecorator : DecoratorRegistration<EntityTemplate, IClassDecorator>
{
    public override string DecoratorId => "MyModule.EntityAuditFieldsDecorator";

    public override IClassDecorator CreateDecoratorInstance(
        EntityTemplate template, 
        IApplication application)
    {
        return new EntityAuditFieldsDecoratorImpl(template);
    }
}

public class EntityAuditFieldsDecoratorImpl : IClassDecorator
{
    private readonly EntityTemplate _template;

    public EntityAuditFieldsDecoratorImpl(EntityTemplate template)
    {
        _template = template;
    }

    public int Priority => 100;

    public string Fields() => @"
    public DateTime CreatedDate { get; set; }
    public DateTime? ModifiedDate { get; set; }";

    public string Methods() => string.Empty;
}

Registration Lifecycle

The Software Factory executes registrations in the following order:
  1. Module Loading - Modules are loaded and their registrations discovered
  2. Template Registration - Register() is called on all ITemplateRegistration implementations
  3. Decorator Registration - Decorators are registered and matched to templates
  4. Template Creation - Template instances are created via factory functions
  5. OnCreated Hook - OnCreated() is called on each template
  6. Configuration - Templates are configured with file metadata
  7. OnConfigured Hook - OnConfigured() is called on each template
  8. AfterTemplateRegistration Hook - AfterTemplateRegistration() is called on each template
  9. Dependency Resolution - Template dependencies are resolved
  10. Execution - Templates are executed in dependency order

Best Practices

Use Dependency Injection

Inject IMetadataManager and other services through the registration constructor.

Filter Models Appropriately

In GetModels(), filter to only the models that should create template instances.

Match Template IDs

Ensure the registration’s TemplateId property matches the template’s constant ID.

Consider Performance

Avoid expensive operations in GetModels() - use metadata queries efficiently.

IntentTemplateBase

Base classes for template implementation

Template Dependencies

Managing dependencies between templates

Output Target

Configuring template output locations

Build docs developers (and LLMs) love