From faec7352fac302fc725cc681b00159bbb9564f15 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 7 Sep 2025 17:26:53 +0900 Subject: [PATCH] Add ConsoleAppBuilder.Run/RunAsync (args, bool disposeService) overload --- .../GeneratorSandbox/GeneratorSandbox.csproj | 2 +- sandbox/GeneratorSandbox/Program.cs | 436 +++--------------- src/ConsoleAppFramework/ConsoleAppBaseCode.cs | 76 ++- 3 files changed, 119 insertions(+), 395 deletions(-) diff --git a/sandbox/GeneratorSandbox/GeneratorSandbox.csproj b/sandbox/GeneratorSandbox/GeneratorSandbox.csproj index d4b72a0c..df0ca9fd 100644 --- a/sandbox/GeneratorSandbox/GeneratorSandbox.csproj +++ b/sandbox/GeneratorSandbox/GeneratorSandbox.csproj @@ -1,4 +1,4 @@ - + Exe diff --git a/sandbox/GeneratorSandbox/Program.cs b/sandbox/GeneratorSandbox/Program.cs index c8b17801..8b9af7a5 100644 --- a/sandbox/GeneratorSandbox/Program.cs +++ b/sandbox/GeneratorSandbox/Program.cs @@ -1,392 +1,84 @@ -#nullable enable +using ConsoleAppFramework; -using CommunityToolkit.Mvvm.ComponentModel; -using ConsoleAppFramework; -//using Microsoft.Extensions.DependencyInjection; -//using Microsoft.Extensions.Hosting; -using System.Transactions; +args = ["hello"]; -[assembly: ConsoleAppFrameworkGeneratorOptions(DisableNamingConversion = true)] +var builder = ConsoleApp.Create(); -args = ["TestCommand", "Run"]; +builder.UseFilter(); +builder.UseFilter(); -//var builder = Host.CreateApplicationBuilder(args); -//var services = builder.Services; +builder.Add(); -//services.AddSingleton(); -//services.AddKeyedSingleton("Key"); +await builder.RunAsync(args); - -//MyObj obj = new(); -//while (obj.Data.Count < 1) -//{ -// obj.Data.Add(0); // <-- CAF008 error here -//} - - -////builder.Build(); -////IHost host; -////host.Run(); - - - -//var app = builder.ToConsoleAppBuilder(); -// var app = ConsoleApp.Create(); -//for (int i = 0; i < 10; i++) -//{ -// app.Add("foo", (int x) => { }); -//} - - -// var hsot = ConsoleApp.ServiceProvider.GetService(typeof(IHost)); -//public void Run(string[] args) -//{ -// BuildAndSetServiceProvider(); -// try -// { -// RunCore(args); -// } -// finally -// { -// if (ServiceProvider is IDisposable d) -// { -// d.Dispose(); -// } -// } -//} - -var app = ConsoleApp.Create(); - -await app.RunAsync(args); - -//await app.RunAsync(args); - -interface ITest +[ConsoleAppFilter] +[ConsoleAppFilter] +public class MyClass { - int Value { get; set; } + [ConsoleAppFilter] + [ConsoleAppFilter] + public void Hello() + { + Console.Write("abcde"); + } } -class Test : ITest +internal class NopFilter1(ConsoleAppFilter next) + : ConsoleAppFilter(next) { - public int Value { get; set; } = 1; + public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) + { + Console.Write(1); + return Next.InvokeAsync(context, cancellationToken); + } } -class KeyedTest : ITest +internal class NopFilter2(ConsoleAppFilter next) + : ConsoleAppFilter(next) { - public int Value { get; set; } = 2; + public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) + { + Console.Write(2); + return Next.InvokeAsync(context, cancellationToken); + } } -//[RegisterCommands(nameof(TestCommand))] -//class TestCommand([FromKeyedServices("Key")] ITest test) -//{ -// public void Run() -// { -// // This value should be 2 but 1 displayed -// Console.WriteLine(test.Value); -// } -//} - -public partial class MyObj : ObservableObject +internal class NopFilter3(ConsoleAppFilter next) + : ConsoleAppFilter(next) { - [ObservableProperty] - private List data = []; + public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) + { + Console.Write(3); + return Next.InvokeAsync(context, cancellationToken); + } } +internal class NopFilter4(ConsoleAppFilter next) + : ConsoleAppFilter(next) +{ + public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) + { + Console.Write(4); + return Next.InvokeAsync(context, cancellationToken); + } +} -//args = ["echo", "--msg", "zzzz"]; - -//// IHostBuilder -//// HostApplicationBuilder -////var app = Host.CreateApplicationBuilder() -//// .ToConsoleAppBuilder(); -//// appBuilder.Build(); - -//// Package Import: Microsoft.Extensions.Configuration.Json -//var app = ConsoleApp.Create() -// .ConfigureDefaultConfiguration() -// .ConfigureServices((configuration, services) => -// { -// // Microsoft.Extensions.Options.ConfigurationExtensions -// services.Configure(configuration.GetSection("Position")); -// }); - -//// Uncomment following line to overwrite args. -// args = ["run", "--project", "foo.csproj", "--", "--foo", "100", "--bar", "bazbaz"]; - -// dotnet run --project foo.csproj -- --foo 100 --bar bazbaz - -//var app = ConsoleApp.Create(); - -//app.Add("run", ([FromKeyedServices("takoyaki")] List testList, string project, ConsoleAppContext context) => -//{ -// // run --project foo.csproj -- --foo 100 --bar bazbaz -// Console.WriteLine(string.Join(" ", context.Arguments)); - -// // --project foo.csproj -// Console.WriteLine(string.Join(" ", context.CommandArguments!)); - -// //IServiceProvider ServiceProvider = null!; -// // ((Microsoft.Extensions.DependencyInjection.IKeyedServiceProvider)ServiceProvider).GetKeyedService(Type, ""); - -// // FromKeyedServicesAttribute -// // IKeyedServiceProvider - -// // --foo 100 --bar bazbaz -// Console.WriteLine(string.Join(" ", context.EscapedArguments!)); -//}); - -//app.Add("foo"); - -//app.UseFilter(); - -//app.Run(args); - - -//internal class NopFilter2([FromKeyedServices("mykey")] List xxxx, ConsoleAppFilter next) : ConsoleAppFilter(next) -//{ -// public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) -// { -// try -// { -// /* on before */ -// await Next.InvokeAsync(context, cancellationToken); // next -// /* on after */ -// } -// catch -// { -// /* on error */ -// throw; -// } -// finally -// { -// /* on finally */ -// } -// } -//} - - -////ConsoleApp.Run(args, (ConsoleAppContext ctx) => { }); - -//// inject options -////public class MyCommand(IOptions options) -////{ -//// public void Echo(string msg) -//// { -//// ConsoleApp.Log($"Binded Option: {options.Value.Title} {options.Value.Name}"); -//// } -////} - -////public class PositionOptions -////{ -//// public string Title { get; set; } = ""; -//// public string Name { get; set; } = ""; -////} - -////internal class ServiceProviderScopeFilter(IServiceProvider serviceProvider, ConsoleAppFilter next) : ConsoleAppFilter(next) -////{ -//// public override async Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) -//// { -//// // create Microsoft.Extensions.DependencyInjection scope -//// await using var scope = serviceProvider.CreateAsyncScope(); - -//// var originalServiceProvider = ConsoleApp.ServiceProvider; -//// ConsoleApp.ServiceProvider = scope.ServiceProvider; -//// try -//// { -//// await Next.InvokeAsync(context, cancellationToken); -//// } -//// finally -//// { -//// ConsoleApp.ServiceProvider = originalServiceProvider; -//// } -//// } -////} - -//// JsonSerializer.Deserialize("foo"); - -////// inject logger to filter -////internal class ReplaceLogFilter(ConsoleAppFilter next, ILogger logger) -//// : ConsoleAppFilter(next) -////{ -//// public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) -//// { -//// ConsoleApp.Log = msg => logger.LogInformation(msg); -//// ConsoleApp.LogError = msg => logger.LogError(msg); - -//// return Next.InvokeAsync(context, cancellationToken); -//// } -////} - -//class MyProvider : IServiceProvider, IAsyncDisposable -//{ -// public void Dispose() -// { -// Console.WriteLine("disposed"); -// } - -// public ValueTask DisposeAsync() -// { -// Console.WriteLine("dispose async"); -// return default; -// } - -// public object? GetService(Type serviceType) -// { -// return null; -// } -//} - -//public class MyService -//{ - -//} - - -//public class MyCommands -//{ -// public MyCommands([FromKeyedServices(10.9)] float kokonimo) -// { - -// } - -// public void Cmd1(int x, int y, ConsoleAppContext ctx) -// { -// } - -// public Task Cmd2([FromKeyedServices(typeof(int))] List l, int x, int y) -// { -// return Task.CompletedTask; -// } -//} - -//public class Tacommands -//{ -// public void HelloWorld(int hogeMoge) -// { -// } -//} - -//namespace ConsoleAppFramework -//{ -// internal static partial class ConsoleApp -// { -// static void Foo() -// { -// var options = JsonSerializerOptions ?? System.Text.Json.JsonSerializerOptions.Default; -// } - -// //public static ConsoleAppBuilder Create(IServiceProvider serviceProvider) -// //{ -// // ConsoleApp.ServiceProvider = serviceProvider; -// // return ConsoleApp.Create(); -// //} - -// //public static ConsoleAppBuilder Create(Action configure) -// //{ -// // var services = new ServiceCollection(); -// // configure(services); -// // ConsoleApp.ServiceProvider = services.BuildServiceProvider(); -// // return ConsoleApp.Create(); -// //} - - - -// //internal partial class ConsoleAppBuilder -// //{ -// // bool requireConfiguration; -// // IConfiguration? configuration; -// // Action? configureServices; -// // Action? configureLogging; - -// // /// Create configuration with SetBasePath(Directory.GetCurrentDirectory()) and AddJsonFile("appsettings.json"). -// // public void ConfigureDefaultConfiguration(Action configure) -// // { -// // var config = new ConfigurationBuilder(); -// // config.SetBasePath(System.IO.Directory.GetCurrentDirectory()); -// // config.AddJsonFile("appsettings.json", optional: true); -// // configure(config); -// // configuration = config.Build(); -// // } - -// // public void ConfigureEmptyConfiguration(Action configure) -// // { -// // var config = new ConfigurationBuilder(); -// // configure(config); -// // configuration = config.Build(); -// // } - -// // public void ConfigureServices(Action configure) -// // { -// // this.configureServices = (_, services) => configure(services); -// // } - -// // public void ConfigureServices(Action configure) -// // { -// // this.requireConfiguration = true; -// // this.configureServices = configure; -// // } - -// // public void ConfigureLogging(Action configure) -// // { -// // this.configureLogging = (_, builder) => configure(builder); -// // } - -// // public void ConfigureLogging(Action configure) -// // { -// // this.requireConfiguration = true; -// // this.configureLogging = configure; -// // } - -// // public void BuildAndSetServiceProvider() -// // { -// // if (configureServices == null && configureLogging == null) return; - -// // if (configureServices != null) -// // { -// // var services = new ServiceCollection(); -// // configureServices?.Invoke(configuration!, services); - -// // if (configureLogging != null) -// // { -// // var config = configuration; -// // if (requireConfiguration && config == null) -// // { -// // config = new ConfigurationRoot(Array.Empty()); -// // } - -// // var configure = configureLogging; -// // services.AddLogging(logging => -// // { -// // configure!(config!, logging); -// // }); -// // } - -// // ConsoleApp.ServiceProvider = services.BuildServiceProvider(); -// // } -// // } -// //} -// } - - -//} - - - - -//namespace HogeHoge -//{ - - - -// public class BatchAttribute : Attribute -// { -// } - - -// public class Batch2Attribute : BatchAttribute -// { -// } - - -//} +internal class NopFilter5(ConsoleAppFilter next) + : ConsoleAppFilter(next) +{ + public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) + { + Console.Write(5); + return Next.InvokeAsync(context, cancellationToken); + } +} +internal class NopFilter6(ConsoleAppFilter next) + : ConsoleAppFilter(next) +{ + public override Task InvokeAsync(ConsoleAppContext context, CancellationToken cancellationToken) + { + Console.Write(6); + return Next.InvokeAsync(context, cancellationToken); + } +} diff --git a/src/ConsoleAppFramework/ConsoleAppBaseCode.cs b/src/ConsoleAppFramework/ConsoleAppBaseCode.cs index 608626bb..13698809 100644 --- a/src/ConsoleAppFramework/ConsoleAppBaseCode.cs +++ b/src/ConsoleAppFramework/ConsoleAppBaseCode.cs @@ -545,7 +545,11 @@ internal static partial class ConsoleApp { internal partial class ConsoleAppBuilder { - public void Run(string[] args) + public void Run(string[] args) => Run(args, true); + + public Task RunAsync(string[] args) => RunAsync(args, true); + + public void Run(string[] args, bool disposeService) { BuildAndSetServiceProvider(); try @@ -554,14 +558,17 @@ public void Run(string[] args) } finally { - if (ServiceProvider is IDisposable d) + if (disposeService) { - d.Dispose(); + if (ServiceProvider is IDisposable d) + { + d.Dispose(); + } } } } - public async Task RunAsync(string[] args) + public async Task RunAsync(string[] args, bool disposeService) { BuildAndSetServiceProvider(); try @@ -575,13 +582,16 @@ public async Task RunAsync(string[] args) } finally { - if (ServiceProvider is IAsyncDisposable ad) - { - await ad.DisposeAsync(); - } - else if (ServiceProvider is IDisposable d) + if (disposeService) { - d.Dispose(); + if (ServiceProvider is IAsyncDisposable ad) + { + await ad.DisposeAsync(); + } + else if (ServiceProvider is IDisposable d) + { + d.Dispose(); + } } } } @@ -610,32 +620,48 @@ internal static partial class ConsoleApp { internal partial class ConsoleAppBuilder { - public void Run(string[] args) + public void Run(string[] args) => Run(args, true, true, true); + + public void Run(string[] args, bool startHost, bool stopHost, bool disposeService) { BuildAndSetServiceProvider(); Microsoft.Extensions.Hosting.IHost? host = ConsoleApp.ServiceProvider?.GetService(typeof(Microsoft.Extensions.Hosting.IHost)) as Microsoft.Extensions.Hosting.IHost; try { - host?.StartAsync().GetAwaiter().GetResult(); + if (startHost) + { + host?.StartAsync().GetAwaiter().GetResult(); + } RunCore(args); } finally { - host?.StopAsync().GetAwaiter().GetResult(); - if (ServiceProvider is IDisposable d) + if (stopHost) { - d.Dispose(); + host?.StopAsync().GetAwaiter().GetResult(); + } + if (disposeService) + { + if (ServiceProvider is IDisposable d) + { + d.Dispose(); + } } } } - public async Task RunAsync(string[] args) + public Task RunAsync(string[] args) => RunAsync(args, true, true, true); + + public async Task RunAsync(string[] args, bool startHost, bool stopHost, bool disposeService) { BuildAndSetServiceProvider(); Microsoft.Extensions.Hosting.IHost? host = ConsoleApp.ServiceProvider?.GetService(typeof(Microsoft.Extensions.Hosting.IHost)) as Microsoft.Extensions.Hosting.IHost; try { - await host?.StartAsync(); + if (startHost) + { + await host?.StartAsync(); + } Task? task = null; RunAsyncCore(args, ref task!); if (task != null) @@ -645,14 +671,20 @@ public async Task RunAsync(string[] args) } finally { - await host?.StopAsync(); - if (ServiceProvider is IAsyncDisposable ad) + if (stopHost) { - await ad.DisposeAsync(); + await host?.StopAsync(); } - else if (ServiceProvider is IDisposable d) + if (disposeService) { - d.Dispose(); + if (ServiceProvider is IAsyncDisposable ad) + { + await ad.DisposeAsync(); + } + else if (ServiceProvider is IDisposable d) + { + d.Dispose(); + } } } }