Git Product home page Git Product logo

consoleappframework's People

Contributors

afernandes avatar cympfh avatar epsilongtmyon avatar erjanmx avatar fornever avatar guitarrapc avatar igadmg avatar itn3000 avatar jaxelr avatar kageshiron avatar masfj avatar mathenn avatar mayuki avatar neuecc avatar nogic1008 avatar taks avatar voxelpluginforproject avatar wipiano avatar xpaw avatar yfakariya avatar zadykian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

consoleappframework's Issues

Proposal: always handle values with dashes as parameter names

Proposal

Change behaviour of ConsoleAppEngine.TryGetInvokeArguments method to always handle values starting with dashes as parameter names but not values.

In this case it would be required to pass value starting with dashes wrapped into quotes. For example:

MyApp.Exe command --some-arg "--arg-value-with-leading-dashes"

Motivation

Current parsing mechanism doesn’t provide correct error messages in case if one of multiple parameters is passed without value. For example:

App definition:

public class CommandTests_Single_Two_Required : ConsoleAppBase
{
    [RootCommand]
    public void Hello(string firstName, string lastName) => Console.WriteLine($"Hello {firstName} {lastName}");
}

Input:

MyApp.Exe --first-name --last-name "TestLastName"

Output:

Required parameter "last-name" not found in argument. args: --first-name --last-name TestLastName

So, "--last-name" is parsed as value of --first-name parameter

Expecting output:

Value for parameter "first-name" is not provided.

Sort/group subcommands in help output.

Currently if commands are added via AddCommand and AddSubcommand they are mixed in help output (looks like they are sorted by Command name alphabetically), so subcommands can be spread through the help list. Like this

add class
create
generate
add workspace
version

Would be great if they are grouped by upper command.

Feature Request: Support Command Aliases

(Previous issue title: Aliases are displayed twice in command list)

On the command help, command aliases are displayed twice.

Sample

Code

var app =
    ConsoleApp.Create(args)
    .AddCommands<Program>();

app.Run();

partial class Program : ConsoleAppBase
{
    [Command(new[] { "s", "sa", "sample" }, "Sample command.")]
    public void Sample() {
        Console.WriteLine("Hello from console app!");
    }
}

Output of dotnet run help

Commands:
  help                        Display help.
  s, sa, sample sa, sample    Sample command.
  version                     Display version.

Aliases sa and sample are displayed twice.

Cause

commandHelpDefinitions.Select(... in method BuildMethodListMessage (here) seems to generate the wrong help text.

x.Command already contains the aliases, but it gets concatinated with x.CommandAliases.

Environment

  • ConsoleAppFramework 4.2.4
  • .NET SDK 7.0.101
  • Windows 10 Pro 22H2 x64

[Help wanted] Prevent the console app to got terminated after the Run method call

So, I'm testing the very friendly and initial examples like that:

var app = ConsoleApp.Create(args);
app.AddCommands<Foo>();
app.Run();

But when I build/run the app, my console just got terminated and I didn't have a chance to make any input. I tried to use Console.ReadLine() right after the app.Run() but it is not working and I didn't get the command response either.

The only way I was able to see it working was by calling this in the terminal at solution directory e.g. dotnet run -- sum 2 2

I would like to have something I could debug, is there a proper way or any tips to achieve that, please? I mean, something to keep console app open and just terminated with some command like e.g. --exit.

Passing a quoted string with a short parameter breaks Microsoft CommandLine engine

Here is my case. I am writing an app which need to accept parameter switches for another app it is using. So for example I am trying to call my app

./myapp command -msg=hello random parameters here

or even like this

./myapp command "-msg=hello random parameters here"

And that break everything with exception System.FormatException: 'The short switch '-msg=hello random parameters here' is not defined in the switch mappings.'

Looks like HostBuilder takes that parameters personal and try to parse them for some reason. Looks like not an issue of ConsoleAppFramework but still maybe there is a way to fix that?

One solution I found is to wrap that as a named parameter. For example

./myapp command --parameters "-msg=hello random parameters here"

But that look ugly. Will require escaping of internal quotes etc.

So the question is is it possible to prevent HostBuilder from parsing parameters, and why is it doing it? I just want to get that strings in my app and don't really care if my data is valid for HostBuilder or not. Or that is a limitation of .net platform and we are doomed to live with that?

If no arguments are passed, no `help` is performed.

I wrote the following code.

    class Program: ConsoleAppBase
    {
        private static async Task Main(string[] args)
        {
            await Host.CreateDefaultBuilder().RunConsoleAppFrameworkAsync<Program>(args);
        }

        public void Run()
        {

        }

        [Command("login")]
        public async Task Login(string ipAddress, string username, string password)
        {
            // login command
        }
    }

I ran as follows, but no help is displayed without arguments.

>sampleapp.exe

>sampleapp.exe help
Usage: sampleapp

Usage: sampleapp <Command>

Commands:
  login

I want help without any arguments.
Please tell me if you have any mistakes.

Unable to implement IDispose in my ConsoleApp

I want to implement the IDispose interface in my console app class, but the framework complains that there are multiple public methods in my class. Could you exclude the public Dispose method when it tries to find the method to run?

Proposal: Boolean option legend should not show its value type

Currently, bool typed options are shown in help message like -o, --option <Boolean> (description...). It looks that specifying boolean value is required despite it is omittable (we can specify the option with -o only in above example). Many users cannot notice this fact. So, it is better to suppress <Boolean>, such as -o, --option (description...) for previous example, when all following conditions are met:

  • The option is optional (has default value).
  • The default value is false.

Any way how to implement sub commands?

Need to implement nested commands, something like

program.exe command subcommand1
program.exe command subcommand2
etc.

Any way how to implement it?

One way that can be possibly implemented by having [Command("command subcommand1")] but that does not work now.

Proposal: New API to return Exit Code

I'm replacing a TRADITIONAL batch program with this Framework.
However, sadly, these OLD programs are linked to other systems by their exit codes.
So I need new API to return an exit code in this framework.

Something like this.

class Program
{
    static Task<int> Main(string[] args)
        => await BatchHost.CreateDefaultBuilder().RunBatchEngineWithExitCodeAsync<SampleBatch>(args);
}

class SampleBatch : BatchBase
{
    [Command("sync")]
    public int ParseInt(string source) => int.TryParse(source, out var i) ? i : -1;

    [Command("async")]
    public async Task<int> ParseIntAsync(string source)
    {
        Context.Logger.LogInformation("Wait...");
        await Task.Delay(1000);
        return ParseInt(source);
    }
}

Global exception handler not catching

currently if there is an exception trown in the app I get the full ToString() of an exception
I would like to add some global exception handler witch is looking like:
System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e) { // do something here Environment.Exit(1); }

but this never catches

I did not find any info on how to handle exceptions in the docs

CommandAttribute did not work?

Environment

  • dotnet core sdk 3.0pre6
  • MicroBatchFramework: 1.2.0

Steps to reproduce

  1. create console project(and set TargetFramework to netcoreapp2.1)
  2. write following source to Program.cs
  3. do dotnet run -- test -arg1 aaaa
using System;
using System.Threading.Tasks;
using MicroBatchFramework;

namespace microbatchframeworktest
{
    class MyBatch : BatchBase
    {
        [Command("test")]
        public void MyTest(string arg1)
        {
            Console.WriteLine("hello {0}", arg1);
        }
    }
    class Program
    {
        static async Task Main(string[] args)
        {
            await BatchHost.CreateDefaultBuilder().RunBatchEngineAsync(args);
        }
    }
}

Expected behavior

print "hello aaaa"

Actual behavior

print "Type or method does not found on this Program. args: test -arg1 aaaa" then exit.

Additional

  • dotnet run -- MyBatch.MyTest -arg1 aaaa seems to work
  • did dotnet run -- list, then output MyBatch.MyTest was output

[RootCommand] for each ConsoleAppBase class

I have 3 classes (A, B, C) to structure my commands. Now i want to have a RootCommand for each of those classes.
I added [RootCommand] over a Function (Func) for each class.
The expected result would be that i can use it like this:

MyTool A
MyTool B
MyTool C

However this does not seem to work, as i have to use it like this:

MyTool A Func
MyTool B Func
MyTool C Func

Is there something wrong with my setup or am i misunderstanding how [RootCommand] should work?

How to override ShowVersion (and ShowHelp)?

Unless I am missing something, I think it's currently not possible to override these to provide my own implementation (I want to print extra stuff in version for example).

Some way to specify my own methods for these that return strings would be great.

Add a way to specify the default value

Currently the default value is taken directly from the method syntax [void Run(int foo = 0)] would yield the default value of 0 in the help message. However, some types can be easily defined as a default, such as DateTime?. In these cases, the null value is checked, and if there, a value is assigned.

So, a method syntax of: void Run(DateTime? date = null) currently shows null, but the actual default is set to DateTime.Today if the value is null.

Can the Options attribute be modified to take an alternative text, or maybe a Default attribute used to override the default behavior?

DI doesn't work on "Development" environment

environment

.NET Core 3.0.100
MicroBatchFramework 1.5.0

repro code

class Program
{
    static async Task Main(string[] args)
    {
        await BatchHost.CreateDefaultBuilder()
            .UseEnvironment("Development") // works fine if this line is commented out
            .ConfigureServices((hostContext, services) =>
            {
                services.AddScoped<IHoge, Hoge>();
            })
            .RunBatchEngineAsync<MyFirstBatch>(args);
    }
}

public interface IHoge
{
    void Test();
}

public class Hoge : IHoge
{
    public void Test() => Console.WriteLine("Hoge");
}

public class MyFirstBatch : BatchBase
{
    private readonly IHoge hoge;

    public MyFirstBatch(IHoge hoge)
    {
        this.hoge = hoge;
    }

    public void Hello()
    {
        hoge.Test();
        Console.WriteLine("MyFirstBatch");
    }
}

expected

Hoge
MyFirstBatch

actual

Fail to create BatchBase instance. Type:ConsoleApp4.MyFirstBatch
System.InvalidOperationException: Cannot resolve 'ConsoleApp4.MyFirstBatch' from root provider because it requires scoped service 'ConsoleApp4.IHoge'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, IServiceScope scope, IServiceScope rootScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Microsoft.Extensions.DependencyInjection.ServiceLookup.IServiceProviderEngineCallback.OnResolve(Type serviceType, IServiceScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at MicroBatchFramework.BatchEngine.RunCore(BatchContext ctx, Type type, MethodInfo methodInfo, String[] args, Int32 argsOffset)

RunConsoleAppFrameworkAsync method only searches ConsoleApp from loaded assemblies

The document of RunConsoleAppFrameworkAsync method says "Run multiple ConsoleApp that are searched from all assemblies". However, when I looked at GetConsoleAppTypes method, it actually only search in assemblies returned by AppDomain.CurrentDomain.GetAssemblies(). The GetAssemblies method returns only loaded assemblies.

Currently, to workaround this, I have to reference a type of target assemblies or force them to be loaded before calling RunConsoleAppFrameworkAsync method.

Feature Request: Allow specifying option description without short name

Background

Currently, help message is generated from [Option] attribute's positional argument. However, for relatively minor options, it is hard to assign short name because they are only 26 chars. So, it is useful to enable specifying help message text without short name.

Proposal

  • Add support for [System.ComponentModel.Description] attribute for command parameters.
  • If both of [Option] with description and [Description] are specified, [Description] to improve sense of unity when options with [Option] and options with [Description] are mixed by specifying all descriptions are specified through [Description] attributes.

Example

public void Foo(
  [Option("i")][Description("Specify input file path.")] string input,
  [Option("o")][Description("Specify output file path.")] string output,
  [Description("Allows overwrite output file.")] bool overwrite = false
)
{
   ...
}

Failed to load assembly 'Microsoft.Bcl.AsyncInterfaces' on .NET Core 3.1

I faced to crash ConsoleAppFramework when it stops its execution.

Workaround

I can avoid this issue with adding explicit dependency to Microsoft.Bcl.AsyncInterface to my app.

Details

Unhandled exception. System.AggregateException: One or more hosted services failed to stop. (Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.  )
 ---> System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.
File name: 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'
   at ConsoleAppFramework.ConsoleAppEngineService.StopAsync(CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at ConsoleAppFramework.ConsoleAppEngineService.StopAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.Internal.Host.StopAsync(CancellationToken cancellationToken)


   --- End of inner exception stack trace ---
   at Microsoft.Extensions.Hosting.Internal.Host.StopAsync(CancellationToken cancellationToken)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.WaitForShutdownAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token)
   at MYAPP.Program.Main(String[] args)
   at MYAPP.Program.<Main>(String[] args)

As long as I investigated this problem, it caused because ConsoleAppFramework indirectly depends on Microsoft.Bcl.AsyncInterfaces via Microsoft.Extensions.Hosting in netstandard2.0 and does not provide netcoreapp3.1.
When MYAPP uses netcoreapp3.1, it ultimately depends on netstandard2.0 ConsoleAppFramework which indirectly depends on Microsoft.Bcl.AsyncInterfaces, and indirectly depends on netcoreapp3.1 Microsoft.Extensions.Hosting which does not depend on Microsoft.Bcl.AsyncInterfaces. So, Microsoft.Bcl.AsyncInterfaces is not included in published app binaries because selected Microsoft.Extensions.Hosting version does not require it.

Proposal

I think possible solution is one of following:

  • Add netcoreapp3.1 version to ConsoleAppFramework.
  • Add explicit dependency for Microsoft.Bcl.AsyncInterface to netstandard2.0 version of ConsoleAppFramework.
  • Write about workaround in Readme.md.

Minimal API

Try to make single-line console application with argument parsing.

Similar as ASP .NET Minimal API.

ConsoleApp.Create(args).Run((string foo, int bar) =>
{
    // do...
}) ;

or(and...)

var app = ConsoleApp.Create(args);
app.AddCommand("foo", (string foo, int bar) =>
{
}) ;

app.AddCommand("bar", ([Option("f")]string foo, [Option("bar")]int bar) =>
{
}) ;

app.Run();

Fail to match method parameter on XXXX in Swagger

 class Program : ConsoleAppBase // inherit ConsoleAppBase
    {
        static async Task Main(string[] args)
        {
            // target T as ConsoleAppBase.
            await Host.CreateDefaultBuilder(args).RunConsoleAppFrameworkWebHostingAsync("http://localhost:12345");
        }

        // allows void/Task return type, parameter is automatically binded from string[] args.
        public void Run2([Option("n", "name of send user.")] string name, int repeat = 3)
        {
            for (int i = 0; i < repeat; i++)
            {
                Console.WriteLine($"Hello My 2 ConsoleApp from {name}");
            }
        }

      //  [Command("timer")]
        public async Task Timer([Option(0)] uint waitSeconds)
        {
            Console.WriteLine(waitSeconds + " seconds");
            while (waitSeconds != 0)
            {
                // ConsoleAppFramework does not stop immediately on terminate command(Ctrl+C)
                // so you have to pass Context.CancellationToken to async method.
                await Task.Delay(TimeSpan.FromSeconds(1), Context.CancellationToken);
                waitSeconds--;
                Console.WriteLine(waitSeconds + " seconds");
            }
        }
    }

when invoke timer throuth swagger will show next error

fail: ConsoleAppFramework.ConsoleAppEngine[0]
      Fail to match method parameter on Program.Timer. args: Program.Timer -waitSeconds 1
      System.InvalidOperationException: Required argument 0 was not found in specified arguments.
         at ConsoleAppFramework.ConsoleAppEngine.TryGetInvokeArguments(ParameterInfo[] parameters, String[] args, Int32 argsOffset, Object[]& invokeArgs, String& errorMessage)
         at ConsoleAppFramework.ConsoleAppEngine.RunCore(Type type, MethodInfo methodInfo, String[] args, Int32 argsOffset)

remove [Option(0)] in method Timer , can solve this problem

q2:how set response body when use WebHost

Supply multiple values using repeated arguments

Allow multiple command line arguments with the same name to bind to an array parameter. This would avoid separating on comma.

public void Command(string[] name)

my-cli command —name Foo —name Bar
name = [“Foo”, “Bar”]

my-cli command —name Foo —name Bar,Baz
name = [“Foo”, “Bar,Baz”]

How can I handle white-space in JSON

How can I use white-space in JSON?
The sample parameters in the document, https://github.com/Cysharp/ConsoleAppFramework#complex-argument ,
> SampleApp.exe -array [10,20,30] -person {\"Age\":10,\"Name\":\"foo\"}
works well from Windows CMD, but
> SampleApp.exe -array [10,20,30] -person {\"Age\":10,\"Name\":\"foo bar\"}
will return the error below:
Parameter "person" fail on JSON deserialize, please check type or JSON escape or add double-quotation. args: -array [10,20,30] -person {"Age":10,"Name":"foo bar"}

Please tell me a solution.

Is it possible to have optional parameters?

Have a command which can accept one or two parameters,
Now if I have it declared like
public async Task Cmd([Option(0)] string p1, [Option(1)] string p2)
it complains that I need two parameters. Can I mark second parameter optional somehow?

upd: Found a solution, declaring an overload with one parameter solves the problem
public async Task Cmd([Option(0)] string p1)

Don't know if that is official supported way.

upd:
That approach produce several help lines in the output.

How to show sub command's help?

When I create console app like below, test.exe sub -help shows sub:-help.

    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                await Host.CreateDefaultBuilder()
                    .RunConsoleAppFrameworkAsync<Commander>(args);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                throw;
            }
        }
    }

    class Commander : ConsoleAppBase
    {
        public void MainCommand([Option(0, "message to show.")] string message)
        {
            Console.WriteLine(message);
        }

        [Command("sub")]
        public void SubCommand([Option(0, "original message.")] string orgMessage)
        {
            Console.WriteLine($"sub:{orgMessage}");
        }
    }

I want to show something like

Usage: test sub <original message.>

Arguments:
  [0] <String>    original message.

What can I do to achieve this ?

Serializing Dictionary<string,string>

Is there any way to serialize arguments into Dictionary<string,string>?

> MyCmd.exe  -q {{"Key1": "Value1*"}}
Error: fail on JSON deserialize, please check type or JSON escape or add double-quotation.

Ctrl+C not captured when waiting on Console.ReadKey

I'm building an interactive console app where arguments can be specified on the command line, or the user will be asked to enter the argument values at run-time.

According to the docs, ConsoleAppFramework handles the cancel event? I've set the shutdown time to zero so I'd expect the app to terminate immediately on Ctrl+C even tho we're waiting on the user.

I've tried handling Ctrl+C myself by setting Console.TreatControlCAsInput = true and checking the returned key info. This seems to work in debug but not when running in release mode.

Any help would be appreciated.

Attaching filter via attribute leads to InvalidOperationException

When ConsoleAppFilter-derived filter is applied via attribute, application crushes with following error:

System.InvalidOperationException: A suitable constructor for type 'ConsoleAppFramework.ConsoleAppFilter' could not be located. Ensure the type is concrete and all parameters of a public constructor are either registered as services or passed as arguments. Also ensure no extraneous arguments are provided.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance[T](IServiceProvider provider, Object[] parameters)
   at ConsoleAppFramework.WithFilterInvoker.InvokeAsync() in /Users/zadykian/Repository/personal/ConsoleAppFramework/src/ConsoleAppFramework/ConsoleAppFilter.cs:line 79
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(Type type, MethodInfo methodInfo, Object instance, String[] args, Int32 argsOffset) in /Users/zadykian/Repository/personal/ConsoleAppFramework/src/ConsoleAppFramework/ConsoleAppEngine.cs:line 191
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(Type type, MethodInfo methodInfo, Object instance, String[] args, Int32 argsOffset) in /Users/zadykian/Repository/personal/ConsoleAppFramework/src/ConsoleAppFramework/ConsoleAppEngine.cs:line 207

パラメータバインディングに失敗する

便利に使わさせていただいています。
Ver.2.4.0に更新したところ、標記の問題が出たので相談させて下さい。

ConsoleApp1.exe
Usage: ConsoleApp1 <str> [options...]

Arguments:
  [0] <String>    str

Options:
  -b, -p_bool <Boolean>    bool (Default: False)

となっている際に、実行結果が下記のようになってしまいます。
(-bがバインドされない)

ConsoleApp1.exe "input" -b true
str:input, bool:True

ConsoleApp1.exe "input" -b false
str:input, bool:True

ConsoleApp1.exe "input" -b True
str:input, bool:True

ConsoleApp1.exe "input" -b False
str:input, bool:True

Ver.2.0.2では起きないようです。
下記が再現ソースです。
ConsoleApp1.zip

お手数ですが、確認をお願いします。

String Paramter in the Format "$(MESSAGE)" results in empty String

I have the following app:

ConsoleApp app = ConsoleApp.Create(args);
app.AddCommands<TestCommand>();
app.Run();

public class TestCommand : ConsoleAppBase
{
    public int Execute(string message)
    {
        Console.WriteLine(message);
        return 0;
    }
}

If I execute this application with the following parameter ' execute --message "$(Message)" ', the parameter 'message' is an empty string. It seems passing a argument in the format "$(Something)" will handled in a special way, but I want just the raw string, so in my testcase "$(Parameter)". Is that possible?

Global filters with dependency injection

The documentation specifies⬇️

// Filter is instantiated by DI so you can get parameter by constructor injection.

But only shows how to add global filters where the instance is instantiated upfront

var app = ConsoleApp.Create(args, options =>
{
    options.GlobalFilters = new ConsoleAppFilter[]
    {
        new MutextFilter() { Order = -9999 } ,
        new LogRunningTimeFilter() { Oder = -9998 }, 
    }
});

Is there a way to use Dependency Injection with global filters, that I've just missed from the documentation?

e.g.

// filter class
public class MyFilter : ConsoleAppFilter
{
  private readonly ILogger<MyFilter> logger;
  public MyFilter(ILogger<MyFilter> logger)
  {
    this.logger = logger;
  }

  public override async ValueTask Invoke(ConsoleAppContext context, Func<ConsoleAppContext, ValueTask> next)
  {
    logger.LogInformation(context.MethodInfo.Name);
    await next(context);
  }
}

// and adding the filter
var builder = ConsoleApp.CreateBuilder(args, options =>
  {
    options.AddFilter<MyFilter>;
  });

Console app that contains a single command doesn't show the detail for help.

When help [command] is executed for an app that contains a single command with CommandAttribute, the app shows the command list rather than the detail of that command.

Steps to reproduce

  1. Create .NET Core Console App named ConsoleApp1 (TargetFramework = netcoreapp2.1; LangVersion = latest)
  2. Install ConsoleAppFramework 2.0.2
  3. dotnet build and dotnet run -p ConsoleApp1 -- help escape
using System;
using System.Threading.Tasks;
using ConsoleAppFramework;
using Microsoft.Extensions.Hosting;
namespace ConsoleApp1
{
    class Program : ConsoleAppBase
    {
        static async Task Main(string[] args)
        {
            await Host.CreateDefaultBuilder().RunConsoleAppFrameworkAsync<Program>(args);
        }
        [Command("escape")]
        public void UrlEscape([Option("i", "URL")] string input = "")
        {
            Console.WriteLine(Uri.EscapeDataString(input));
        }
    }
}

Expected

Usage: ConsoleApp1 escape [options...]

Options:
  -i, -input <String>    URL (Default: )

Actual

Usage: ConsoleApp1 <Command>

Commands:
  escape     

Workarounds

  • Don't use CommandAttribute for a single command.
  • Add any command.

Environment

  • Windows 10 v1809
  • Visual Studio 2017.9
  • .NET Core SDK 2.1.511
  • .NET Core runtime 2.1.15

Change usage name

Is there any way to change the usage name, besides renaming your project?
image
To be more specific I'd like to replace Retrospect.CLI in the image above with something else.

More than 16 arguments when using a class method

This works:

ConsoleApp.Run(args, (
    bool a1,
    bool a2,
    bool a3,
    bool a4,
    bool a5,
    bool a6,
    bool a7,
    bool a8,
    bool a9,
    bool a10,
    bool a11,
    bool a12,
    bool a13,
    bool a14,
    bool a15,
    bool a16,
    bool a17,
    bool a18,
    bool a19,
    string a20 = "test"
    ) => { });

But when doing the following, it fails to generate because Func<> does not accept more than 16 arguments (it doesn't generate a delegate like the anonymous lambda does).

Argument 2: cannot convert from 'method group' to 'System.Func'

public partial class Test
{
	public static void Main(string[] args)
	{
		var test = new Test();
		ConsoleApp.Run(args, test.Handle);
	}
	
	public void Handle(
		bool a1,
		bool a2,
		bool a3,
		bool a4,
		bool a5,
		bool a6,
		bool a7,
		bool a8,
		bool a9,
		bool a10,
		bool a11,
		bool a12,
		bool a13,
		bool a14,
		bool a15,
		bool a16,
		bool a17,
		bool a18,
		bool a19,
		string a20 = "test"
	)
	{
		//
	}
}

Side question: would it be possible to make it support class constructors, so that I could use readonly fields for options? For example: ConsoleApp.Run<Test>(args);

Do not print the stack trace for `ArgumentException`

Since it's being thrown by the generated code and is expected to be visible by the user, I don't think the stacktrace provides any value.

Current:

System.ArgumentException: Argument '-abc' does not found in command prameters.
   at ConsoleAppFramework.ConsoleApp.ThrowArgumentNameNotFound(String argumentName) in ConsoleApp.cs:line 110
   at ConsoleAppFramework.ConsoleApp.Run(String[] args, Func`15 command) in ConsoleApp.Run.g.cs:line 242

Suggestion:

Argument '-abc' does not found in command prameters.

WebHost Return Value

It would be helpful to be able to return a value instead of the log output, especially in the case of a WebHost.

public class Foo : ConsoleAppBase
{
    public string Echo(string msg)
    {
        return msg;
    }

    public async Task<int> Sum(int x, int y)
    {
        return await Task<int>.Run(()=>
        {
             int result = x + y;
             Console.WriteLine($"The result is {result}");  //Not returned by WebHost 
                                                                                   //OR encapsulated in return object { value: result, output: console output }
             return result;  
        });
    }
}

to 1.0.0 release

  • More Unit Test
  • Swagger Integration
  • Command Alias
  • Override Help and List
  • Pack to Docker Sample
  • Scheduler Sample
  • Modify CreateDefaultBuilder

Indexed Options do not work properly

インデックス付きオプションがインデックス無しのオプションと組み合わせて指定されると期待した動作をしません。他の名前付きオプションを取り除いた状態から0,1,2...とインデックスオプションを解決するのが自然かと思います。

sampe

class Program : ConsoleAppBase
{
    static async Task Main()
    {
        Console.WriteLine("(1) -number 5 foo");
        var args = new string[] { "-number", "5", "foo" };
        await Host.CreateDefaultBuilder().RunConsoleAppFrameworkAsync<Program>(args);

        Console.WriteLine("(2) bar -number 5 foo");
        args = new string[] { "bar", "-number", "5", "foo" };
        await Host.CreateDefaultBuilder().RunConsoleAppFrameworkAsync<Program>(args);
    }

    public void Hello(int number, [Option(0)] string file = null)
    {
        Console.WriteLine(file);
        Console.WriteLine(number);
    }
}

expected

(1) -number 5 foo
foo
5
(2) bar -number 5 foo
bar
5

actual

(1) -number 5 foo
5
5
(2) bar -number 5 foo
-number
5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.