Overview
Decorator execution in Intent Architect follows a well-defined lifecycle that integrates with the Software Factory’s template execution process. Understanding this lifecycle is essential for building decorators that interact correctly with templates and other decorators.
Execution Flow
Decorators are executed as part of the template generation process:
IDecoratorExecutionHooks
The IDecoratorExecutionHooks interface allows decorators to execute logic before template execution begins.
namespace Intent . Modules . Common
{
public interface IDecoratorExecutionHooks
{
void BeforeTemplateExecution ();
}
}
BeforeTemplateExecution
Called for all decorators before any template’s TransformText method is invoked.
Hook method called during the BeforeTemplateExecution phase of the Software Factory execution lifecycle. Use this to perform initialization or preparation work before template generation begins.
Implementing Execution Hooks
using Intent . Engine ;
using Intent . Modules . Common ;
using Intent . Modules . Common . Templates ;
public class MyDecoratorWithHooks : DecoratorBase ,
IMyDecorator ,
IDecoratorExecutionHooks
{
private readonly IMyTemplate _template ;
private readonly IApplication _application ;
private bool _isInitialized ;
public MyDecoratorWithHooks ( IMyTemplate template , IApplication application )
{
_template = template ;
_application = application ;
}
public void BeforeTemplateExecution ()
{
// Perform initialization work
// This runs once before all templates execute
if ( ! _isInitialized )
{
PrepareResources ();
_isInitialized = true ;
}
}
private void PrepareResources ()
{
// Load data, validate configuration, etc.
}
public string GetDecoratorContent ()
{
// This is called during template execution
return "// Decorator content" ;
}
}
DecoratorExecutionHooksFactoryExtension
The framework includes a built-in factory extension that orchestrates decorator execution hooks.
namespace Intent . Modules . Common . Plugins
{
public class DecoratorExecutionHooksFactoryExtension : FactoryExtensionBase
{
public override string Id => "Intent.Common.DecoratorExecutionHooks" ;
public override int Order => - 1 ;
protected override void OnBeforeTemplateExecution ( IApplication application )
{
application . Projects
. SelectMany ( x => x . TemplateInstances )
. Where ( HasDecorators )
. SelectMany ( GetDecorators )
. OfType < IDecoratorExecutionHooks >()
. ToList ()
. ForEach ( x => x . BeforeTemplateExecution ());
base . OnBeforeTemplateExecution ( application );
}
}
}
This factory extension has an Order of -1, ensuring it runs early in the execution lifecycle.
Decorator Dispatcher
The DecoratorDispatcher<TDecorator> class manages decorator invocation within templates.
namespace Intent . Modules . Common . Templates
{
public class DecoratorDispatcher < TDecorator >
where TDecorator : ITemplateDecorator
{
public DecoratorDispatcher ( Func < IEnumerable < TDecorator >> loadDecorators );
public string Dispatch ( Func < TDecorator , string > doIt );
public TResult Dispatch < TResult >( Func < IEnumerable < TDecorator >, TResult > doIt );
public void Dispatch ( Action < TDecorator > doIt );
public IEnumerable < TDecorator > GetDecorators ();
}
}
Methods
Executes a function on each decorator and aggregates string results. Function to execute on each decorator that returns a string.
Executes a function with all decorators and returns a result. doIt
Func<IEnumerable<TDecorator>, TResult>
Function to execute with the collection of decorators.
Executes an action on each decorator. Action to execute on each decorator.
Returns all decorators, loading them if not already loaded.
Using DecoratorDispatcher
public class MyTemplate : CSharpTemplateBase < IClass >,
IHasDecorators < IMyDecorator >
{
private readonly DecoratorDispatcher < IMyDecorator > _decorators ;
public MyTemplate ( IOutputTarget outputTarget , IClass model )
: base ( "MyTemplate" , outputTarget , model )
{
_decorators = new DecoratorDispatcher < IMyDecorator >(
() => GetDecorators ());
}
public override string TransformText ()
{
var usings = _decorators . Dispatch ( d => d . GetUsings ());
var methods = _decorators . Dispatch ( d => d . GetMethods ());
// Perform custom logic with all decorators
_decorators . Dispatch ( decorators =>
{
foreach ( var decorator in decorators )
{
decorator . Initialize ();
}
return 0 ;
});
return $@"
{ usings }
namespace { Namespace }
{{
public class { ClassName }
{{
{ methods }
}}
}}
" ;
}
}
Execution Order
Decorators execute in priority order (lowest to highest):
public IEnumerable < IMyDecorator > GetDecorators ()
{
return ExecutionContext . Decorators
. OfType < IMyDecorator >()
. Where ( x => /* filter for this template */ )
. OrderBy ( x => x . Priority ); // Critical for correct order
}
Always sort decorators by Priority when returning them from GetDecorators(). Failure to do so may result in unpredictable execution order.
Template Decorator Extensions
The framework provides helper methods for aggregating decorator outputs:
namespace Intent . Modules . Common . Templates
{
public static class TemplateDecoratorExtensions
{
public static string Aggregate < TDecorator >(
this IEnumerable < TDecorator > decorators ,
Func < TDecorator , string > property )
where TDecorator : ITemplateDecorator ;
public static string Aggregate < TDecorator >(
this IEnumerable < TDecorator > decorators ,
Func < TDecorator , string []> property )
where TDecorator : ITemplateDecorator ;
}
}
Usage Example
// Aggregate single string values
var usings = decorators . Aggregate ( d => d . GetUsings ());
// Aggregate string arrays
var methods = decorators . Aggregate ( d => d . GetMethods ());
Best Practices
Initialize Early Use BeforeTemplateExecution for expensive initialization that should happen once
Lazy Loading DecoratorDispatcher loads decorators lazily on first use
Order Matters Always sort decorators by Priority in GetDecorators()
Avoid Side Effects Decorator methods should be idempotent when possible
Common Patterns
Content Aggregation
var content = _decorators . Dispatch ( d => d . GetContent ());
Conditional Execution
var decorators = _decorators . GetDecorators ()
. Where ( d => d . ShouldApply ())
. ToList ();
Chained Operations
_decorators . Dispatch ( d =>
{
d . Initialize ();
d . Process ();
});