Extensions Edit on GitHub


Jasper comes with its own extension system heavily influenced by its FubuMVC predecessor. The basic concept is just based on the IJasperExtension shown below:


public interface IJasperExtension
{
    void Configure(JasperRegistry registry);
}

So, what can you do in an extension? Basically anything you can configure in a Jasper application can be altered by an IJasperExtension. Here's a contrived example:


public class SampleExtension : IJasperExtension
{
    public void Configure(JasperRegistry registry)
    {
        // Not sure *why* you'd do this, but you could
        registry.Configuration.AddJsonFile("someFile.json");


        // Add service registrations
        registry.Services.AddTransient<IFoo, Foo>();

        // Alter settings within the application
        registry.Settings.Alter<MessagingSettings>(_ =>
        {
            _.JsonSerialization.TypeNameHandling = TypeNameHandling.All;
        });

    }
}

Do note that in the case of service registrations and any kind of Settings.Apply() calls, the extension alterations are applied first before any registrations or declarations in the main JasperRegistry. What this means in effect is just that the application configuration takes precedence over extensions.

Now, on to how you would consume extensions in your projects:

Explicitly Loading Extensions

You can also explicitly create and consume IJasperExtension classes that are not automatically loaded through the [JasperModule] attribute that are be applied using the JasperRegistry.Include() method shown below:


var registry = new JasperRegistry();
registry.Include<OptionalExtension>();

Auto Discovery of Extensions

When you build an extension, you also have the option to make a single extension be auto-discoverable from an external assembly. To make that concrete, here's an auto-discovered extension in the Jasper.Marten library that wires up integration with a Marten database:


[assembly:JasperModule(typeof(MartenExtension))]

namespace Jasper.Persistence.Marten
{
    public class MartenExtension : IJasperExtension
    {
        public void Configure(JasperRegistry registry)
        {
            registry.Services.AddSingleton<IDocumentStore>(x =>
            {
                var storeOptions = x.GetService<StoreOptions>();
                var documentStore = new DocumentStore(storeOptions);
                return documentStore;
            });

            registry.Handlers.GlobalPolicy<FineGrainedSessionCreationPolicy>();


            registry.Services.AddScoped(c => c.GetService<IDocumentStore>().OpenSession());
            registry.Services.AddScoped(c => c.GetService<IDocumentStore>().QuerySession());

            registry.CodeGeneration.Sources.Add(new SessionVariableSource());

        }
    }


}

When a Jasper application is being bootstrapped, it looks for any assemblies in the application's bin directory that are marked with the [JasperModule] attribute to determine the extension types that should be automatically applied to the application. In the case above, the Marten extension would be discovered at bootstrapping time and the MartenExtension would be applied to the application.

Importing Http Endpoints or Message Handlers

It's perfectly possible to add additional HTTP routes or message handlers in extensions using the explicit JasperRegistry.Handlers.IncludeType() or JasperRegistry.Http.Actions.IncludeType() methods.