This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
mfgames-toolbuilder-cil/src/MfGames.ToolBuilder/ToolService.cs
Dylan R. E. Moonfire ad0525be04 feat: initial commit
2021-09-10 12:33:42 -05:00

140 lines
4 KiB
C#

using System;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Invocation;
using System.CommandLine.Parsing;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Serilog;
#pragma warning disable Serilog004
// ReSharper disable TemplateIsNotCompileTimeConstantProblem
// ReSharper disable SuspiciousTypeConversion.Global
namespace MfGames.ToolBuilder
{
/// <summary>
/// Implements the command-line shell for generating the static site.
/// </summary>
public class ToolService : IHostedService
{
private readonly IList<ITopCommand> commands;
private readonly ConfigToolService configService;
private readonly IHostApplicationLifetime lifetime;
private readonly ILogger logger;
private readonly LoggingToolService loggingService;
public ToolService(
ILogger logger,
IHostApplicationLifetime lifetime,
IList<ITopCommand> commands,
ConfigToolService configService,
LoggingToolService loggingService)
{
this.lifetime = lifetime;
this.commands = commands;
this.configService = configService;
this.loggingService = loggingService;
this.logger = logger.ForContext<ToolService>();
}
/// <inheritdoc />
public Task StartAsync(CancellationToken cancellationToken)
{
this.lifetime.ApplicationStarted
.Register(
() =>
{
Task.Run(
async () =>
await this.RunAsync().ConfigureAwait(false),
cancellationToken);
});
return Task.CompletedTask;
}
/// <inheritdoc />
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private RootCommand CreateRootCommand()
{
// Create the root command and add in the top-level commands
// underneath it.
var root = new RootCommand();
foreach (var command in this.commands)
{
root.AddCommand((Command)command);
}
// Add the universal options.
this.loggingService.AddOptions(root);
this.configService.AddOptions(root);
// Return the resulting container.
return root;
}
private void OnException(Exception exception, InvocationContext context)
{
if (exception is ToolException toolException)
{
this.logger.Fatal(toolException.Message);
foreach (var message in toolException.Messages)
{
this.logger.Fatal(message);
}
Environment.ExitCode = toolException.ExitCode;
}
else
{
this.logger.Fatal(
exception,
"Unhandled exception!");
}
}
private async Task RunAsync()
{
try
{
// Build the command tree.
RootCommand root = this.CreateRootCommand();
string[] args = Environment.GetCommandLineArgs();
// Execute the command.
this.logger.Verbose(
"Running the command-line arguments: {Arguments}",
args);
Environment.ExitCode = await new CommandLineBuilder(root)
.UseDefaults()
.UseExceptionHandler(this.OnException)
.Build()
.InvokeAsync(args)
.ConfigureAwait(false);
}
finally
{
// Stop the application once the work is done.
this.lifetime.StopApplication();
}
}
}
}