Search Results for

    Show / Hide Table of Contents

    Software factory events

    Software factory events allow modules to interact with each other in a decoupled manner, a Template or Software Factory Extension can publish an event without having to be directly aware of any subscribers of that event. They enable use cases like different modules being able to service cross-cutting architectural concerns.

    For example, a template could publish an event requesting its type be registered in a dependency injection container. The user of the module could then choose to install one of a variety of available dependency injection modules which are all listening for that event and will register the type in a technology specific way, the particular installed dependency injection module (perhaps Ninject), could be uninstalled and an alternative module (perhaps AutoFac) could be installed instead and because they both listen for the same event, the system still works with the original event publishing template not needing to be aware of which module is installed.

    Subscribing and consuming an event

    Create an event type (typically in a "third", common project), for example:

    public class RegistrationRequest
    {
        public RegistrationRequest(IClassProvider template)
        {
            Template = template;
        }
    
        public IClassProvider Template { get; set; }
    }
    

    In your template's constructor, subscribe to the event:

    ExecutionContext.EventDispatcher.Subscribe<RegistrationRequest>(Handle);
    

    Handler above refers to a method in a class to handle the event, the implementation of which could be like so:

    private void Handle(RegistrationRequest request)
    {
        AddTemplateDependency(TemplateDependency.OnTemplate(request.Template)); // Will add project dependencies if needed
        _typesToRegister.Add($"{request.Template.Namespace}.{request.Template.ClassName}");
    }
    

    Add a field to the template to hold the types:

    private readonly List<string> _typesToRegister = new();
    

    The .tt file can then be updated to make use of these types:

    namespace <#= Namespace #>
    {
        public class <#= ClassName #>
        {
            public void DoRegistrations()
            {
    <# foreach (var type in _typesToRegister) { #>
                DoRegistration(typeof(<#= UseType(type) #>));
    <# } #>
            }
    
            public void DoRegistration(Type typeToRegister)
            {
                // Custom registration logic here...
            }
        }
    }
    

    Publishing an event

    Publishing of events must be done in the overridden BeforeTemplateExecution() method. Publishing from a template constructor will not work reliably because the software factory instantiates templates in an undefined order meaning that event subscribers may not have been instantiated yet and thus will not receive the published event.

    If not done already, override the BeforeTemplateExecution() method and publish from inside of it:

    public override void BeforeTemplateExecution()
    {
        base.BeforeTemplateExecution();
        ExecutionContext.EventDispatcher.Publish(new RegistrationRequest(this));
    }
    

    Conclusion

    When the above event is published, the subscriber adds its type to a list and a template's dependencies which later during the software factory execution is used when generating the template.

    • Edit this page
    ☀
    ☾
    In this article
    Back to top Copyright © 2017-, Intent Software Pte Ltd.