Metadata is the foundation of Intent Architect’s code generation system. It represents the models, configurations, and design-time information that templates use to generate code.
Templates access metadata through strongly-typed API models:
public class CommandHandlerTemplate : CSharpTemplateBase<CommandModel, CommandHandlerDecorator>{ public CommandHandlerTemplate(IOutputTarget outputTarget, CommandModel model) : base(TemplateId, outputTarget, model) { // Model contains metadata about the command var commandName = model.Name; var returnType = model.TypeReference; var parameters = model.Parameters; }}
Intent Architect generates strongly-typed API models for working with metadata. These are typically found in modules like Intent.Modelers.Services.Api:
using Intent.Metadata.Models;public class CommandModel : IMetadataModel{ public CommandModel(IElement element) { Element = element; } public IElement Element { get; } public string Id => Element.Id; public string Name => Element.Name; public ITypeReference TypeReference => Element.TypeReference; public IList<ParameterModel> Parameters => Element.ChildElements .Where(x => x.SpecializationType == "Parameter") .Select(x => new ParameterModel(x)) .ToList(); public bool HasStereotype(string stereotypeName) { return Element.HasStereotype(stereotypeName); } public IStereotype GetStereotype(string stereotypeName) { return Element.GetStereotype(stereotypeName); }}
// Get all domain entitiesvar entities = _metadataManager.Domain(application).GetDomainModels();// Get all servicesvar services = _metadataManager.Services(application).GetServiceModels();// Get all DTOsvar dtos = _metadataManager.Services(application).GetDTOModels();// Get all commands (CQRS)var commands = _metadataManager.Services(application).GetCommandModels();// Get all queries (CQRS)var queries = _metadataManager.Services(application).GetQueryModels();
Templates can resolve types from metadata to template-generated class names:
// Get type name from another templatestring dtoTypeName = GetTypeName("Application.Contract.Dto", model.TypeReference);// With full type reference resolutionstring entityTypeName = GetTypeName(model.TypeReference);// Check if nullablestring typeName = model.TypeReference.IsNullable ? $"{GetTypeName(model.TypeReference)}?" : GetTypeName(model.TypeReference);// Handle collectionsif (model.TypeReference.IsCollection){ string itemType = GetTypeName(model.TypeReference.Element); string collectionType = $"List<{itemType}>";}
Type resolution connects metadata models to the actual generated C# types, enabling cross-template references.
Templates register type sources to enable type resolution:
internal static void Configure(ICSharpFileBuilderTemplate template, CommandModel model){ // Register where to look for types template.AddTypeSource(TemplateRoles.Application.Command); template.AddTypeSource(TemplateRoles.Domain.Enum); template.AddTypeSource(TemplateRoles.Application.Contracts.Dto); template.AddTypeSource(TemplateRoles.Application.Contracts.Enum); // Now GetTypeName can resolve types from these templates}
Here’s how metadata flows through a complete code generation scenario:
1
User Creates Model
User creates a CreateOrder command in the Services designer with parameters ProductId and Quantity
2
Metadata is Stored
Intent Architect stores this as metadata with properties, type references, and any applied stereotypes
3
Template Queries Metadata
CommandHandlerTemplateRegistration queries for all command models via IMetadataManager
4
Template Generates Code
CommandHandlerTemplate receives the CommandModel and generates:
public class CreateOrderHandler : IRequestHandler<CreateOrderCommand>{ public async Task Handle(CreateOrderCommand request, CancellationToken cancellationToken) { // Generated from metadata var productId = request.ProductId; var quantity = request.Quantity; }}