Application - Nano-Core/Nano.Library GitHub Wiki

Table of Contents


Summary

In Nano, an application refers to the part of defining, building and running a host process.

The implementation isn't much different from the regular approach, when building .Net Core applications. The WebHost is being configured, then built and finally executed. During startup dependencies are registered, and components are configured and initialized. The supplied configuration (appsettings.json), allows for a fine-grained control over the behavior of these dependencies and components.

A few abstractions and interfaces are used to control an application. This resembles the startup.cs class you would normally implement in .Net core, but includes much more. The interface IApplication defines an application. When building the WebHost of the application, the interface is injected as dependency, resolving to the type implemented in your application. The abstract class BaseApplication, implements IApplication, and most importantly, it contains a static method ConfigureApp<TApplication>(...), that is responsible for initializing and configuring the application.

Nano comes with a concrete DefaultApplication implementation, deriving directly from BaseApplication. That is in most cases sufficient, avoiding having to implement a custom implementation.

Object Model Diagram

Applications


Configuration

The appsettings.json contains the configurational information used by Nano, when initializing and building the application.

The App section of the configuration defines behavior related to the application. The section is deserialized into an instance of AppOptions, and injected as dependency during startup, thus available for injection throughout the application.

See Appendix - App Settings for details about the app section and the meaning of the variables.

App Section
"App": {
  "Name": "Application",
  "EntryPoint": "Application.dll",
  "Description": null,
  "Version": "1.0.0.0",
  "TermsOfService": null,
  "DefaultTimeZone": "UTC",
  "Cultures": {
    "Default": "en-US",
    "Supported": [
      "en-US"
    ]
  }
}

Start-Up

The application implementation in nano, is essentially the startup.cs class of .Net Core.

The DefaultApplication implementation is the default startup class, and normally deriving your own implementation isn't needed. In fact, it's recommended not to, and instead configure any custom initialization within the .ConfigureServices(...) inline expression, as explained later. Is a more advanced setup required, and implementing a custom startup class can't be avoided, derive the implementation from one of the provided application classes, that in turn derives from DefaultApplication, and override any methods as needed. For example, in order to inject custom middleware.
Remember to invoke base method implementations!

Sample Implementation
public class MyApplication : DefaultApplication 
{ 
    public MyApplication(IConfiguration configuration)
        : base(configuration)
    {

    }
}

Build and Run

This covers the entry point of the application, and how the startup implementation is applied and executed.

The DefaultApplication doesn't provide any initialization alone, and using it directly would manually require to declare and instantiate one of the IHostBuilder implementations of .Net Core. Nano provides application implementations for a WebApplication and a ConsoleApplication.

The application implementation should include a static method to retrieve an implementation of IHostBuilder. The included application implementations already includes such a method, .ConfigureApp(...). Invoke the method from the Main(...) method of Program class, and configure any additional dependencies inline in the ConfigureServices(x => ...) method.

When having a custom application implementation, either implement your own static method returning the appropriate IHostBuilder implementation, or use the method of one of the included application implementations. The later, can be accomplished by passing the custom application type as generic parameter, to the .ConfigureApp<TApplication>(...) method overload of one of the included application implementations, as shown below.

Sample implementation
// With default IApplication implementation
public class Program
{
    public static void Main()
    {
        WebApplication
            .ConfigureApp()
            .ConfigureServices(x =>
            {
                // Additional dependencies...
            })
            .Build()
            .Run();
    }
}

// With custom IApplication implementation
public class Program
{
    public static void Main()
    {
        WebApplication
            .ConfigureApp<MyApplication>()
            .ConfigureServices(x =>
            {
                // Additional dependencies...
            })
            .Build()
            .Run();
    }
}

Background Jobs

Nano supports running background jobs upon start-up.

Derive an implementation from the abstract BaseStartupTask, and the task dependency will automatically be registered and started during application start-up.

The BaseStartupTask implements IHostedService abstractly, and contains a mechanism for controlling the number of background tasks running, ensuring proper completion when application shuts down.

public class MyStartUpTask : BaseStartupTask
{
    public MyStartUpTask(StartupTaskContext startupTaskContext) 
        : base(startupTaskContext)
    {
    }

    public override Task StartAsync(CancellationToken cancellationToken = default)
    {
        return Task.CompletedTask;
    }

    public override Task StopAsync(CancellationToken cancellationToken = default)
    {
        return Task.CompletedTask;
    }
}

Injected Services

When building the Host, dependencies related to hosting is configured and initialized. This evolves around defining the process and environment in which the application is executing in.

Dependencies:
  • Nano.App.AppOptions
  • Nano.App.BaseApplication
  • Nano.App.DefaultApplication
  • Nano.App.Interfaces.IApplication
  • Nano.App.StartUp.Tasks.BaseStartUpTask

For a full list of services and dependencies, see Injected Dependencies