CliArgumentAttribute Class

Specifies a class property that represents an argument which is a value that can be passed on the command line to a command or an option.
C#
[CliArgument]
public string SomeCliArgument { get; set; }

Note that an argument is required if the decorated property does not have a default value (set via a property initializer), see Required property for details.

Arguments: An argument is a value passed to an option or a command. The following examples show an argument for the verbosity option and an argument for the build command.

console
dotnet tool update dotnet-suggest --verbosity quiet --global
                                              ^---^
console
dotnet build myapp.csproj
             ^----------^
Arguments can have default values that apply if no argument is explicitly provided. For example, many options are implicitly Boolean parameters with a default of true when the option name is in the command line.

Definition

Namespace: DotMake.CommandLine
Assembly: DotMake.CommandLine (in DotMake.CommandLine.dll) Version: 1.8.8
C#
public class CliArgumentAttribute : Attribute
Inheritance
Object    Attribute    CliArgumentAttribute

Example

C#
//Delegate-based model
//In Program.cs, add this simple code:
Cli.Run(([CliArgument] string argument1, bool option1) =>
{
    Console.WriteLine($@"Value for {nameof(argument1)} parameter is '{argument1}'");
    Console.WriteLine($@"Value for {nameof(option1)} parameter is '{option1}'");
});

//Or:
Cli.Run(Method);

void Method([CliArgument] string argument2, bool option2)
{
    Console.WriteLine($@"Value for {nameof(argument2)} parameter is '{argument2}'");
    Console.WriteLine($@"Value for {nameof(option2)} parameter is '{option2}'");
}
C#
// Class-based model
// Create a simple class like this:

[CliCommand(Description = "A root cli command")]
public class RootCliCommand
{
    [CliOption(Description = "Description for Option1")]
    public string Option1 { get; set; } = "DefaultForOption1";

    [CliArgument(Description = "Description for Argument1")]
    public string Argument1 { get; set; }

    public void Run()
    {
        Console.WriteLine($@"Handler for '{GetType().FullName}' is run:");
        Console.WriteLine($@"Value for {nameof(Option1)} property is '{Option1}'");
        Console.WriteLine($@"Value for {nameof(Argument1)} property is '{Argument1}'");
        Console.WriteLine();
    }
}

        //In Program.cs, add this single line:
        Cli.Run<RootCliCommand>(args);

        //If you need to simply parse the command-line arguments without invocation, use this:
        var parseResult = Cli.Parse<RootCliCommand>(args);
        var rootCliCommand = parseResult.Bind<RootCliCommand>();
C#
// Sub-commands can get a reference to the parent command by adding a property of the parent command type.

[CliCommand(Description = "A root cli command with children that can access parent commands")]
public class ParentCommandAccessorCliCommand
{
    [CliOption(
        Description = "This is a global option (Recursive option on the root command), it can appear anywhere on the command line",
        Recursive = true)]
    public string GlobalOption1 { get; set; } = "DefaultForGlobalOption1";

    [CliArgument(Description = "Description for RootArgument1")]
    public string RootArgument1 { get; set; }

    public void Run(CliContext context)
    {
        context.ShowValues();
    }

    [CliCommand(Description = "A nested level 1 sub-command which accesses the root command")]
    public class Level1SubCliCommand
    {
        [CliOption(
            Description = "This is global for all sub commands (it can appear anywhere after the level-1 verb)",
            Recursive = true)]
        public string Level1RecursiveOption1 { get; set; } = "DefaultForLevel1RecusiveOption1";

        [CliArgument(Description = "Description for Argument1")]
        public string Argument1 { get; set; }

        // The parent command gets automatically injected
        public ParentCommandAccessorCliCommand RootCommand { get; set; }

        public void Run(CliContext context)
        {
            context.ShowValues();
        }

        [CliCommand(Description = "A nested level 2 sub-command which accesses its parent commands")]
        public class Level2SubCliCommand
        {
            [CliOption(Description = "Description for Option1")]
            public string Option1 { get; set; } = "DefaultForOption1";

            [CliArgument(Description = "Description for Argument1")]
            public string Argument1 { get; set; }

            // All ancestor commands gets injected
            public ParentCommandAccessorCliCommand RootCommand { get; set; }
            public Level1SubCliCommand ParentCommand { get; set; }

            public void Run(CliContext context)
            {
                context.ShowValues();

                Console.WriteLine();
                Console.WriteLine(@$"Level1RecursiveOption1 = {ParentCommand.Level1RecursiveOption1}");
                Console.WriteLine(@$"parent Argument1 = {ParentCommand.Argument1}");
                Console.WriteLine(@$"GlobalOption1 = {RootCommand.GlobalOption1}");
                Console.WriteLine(@$"RootArgument1 = {RootCommand.RootArgument1}");
            }
        }
    }
}

Constructors

CliArgumentAttributeInitializes a new instance of the CliArgumentAttribute class

Properties

AllowedValues Gets or sets the list of allowed values for an argument.

Configures an argument to accept only the specified values, and to suggest them as command line completions.

Note that if the argument type is an enum, values are automatically added.

Arity Gets or sets the arity of the argument. The arity refers to the number of values that can be passed on the command line.

In most cases setting argument arity is not necessary as it is automatically determined based on the argument type (the decorated property's type):

  • Boolean -> ArgumentArity.ZeroOrOne
  • Collection types -> ArgumentArity.ZeroOrMore
  • Everything else -> ArgumentArity.ExactlyOne
Description Gets or sets the description of the argument. This will be displayed in usage help of the command line application.
HelpName Gets or sets the name of the argument when displayed in help.
Hidden Gets or sets a value indicating whether the argument is hidden.

You might want to support a command, option, or argument, but avoid making it easy to discover. For example, it might be a deprecated or administrative or preview feature. Use the Hidden property to prevent users from discovering such features by using tab completion or help.

Name Gets or sets the name of the argument that will be used mainly for displaying in usage help of the command line application.

If not set (or is empty/whitespace), the name of the property that this attribute is applied to, will be used to generate argument name automatically: These suffixes will be stripped from the property name: RootCliCommandArgument, RootCommandArgument, SubCliCommandArgument, SubCommandArgument, CliCommandArgument, CommandArgument, CliArgument, Argument. Then the name will be converted to kebab-case, for example:

  • If property name is Output or OutputArgument or OutputCliArgument -> argument name will be output
  • If property name is ProjectPath or ProjectPathArgument or ProjectPathCliArgument -> argument name will be project-path

Default convention can be changed via parent command's NameCasingConvention property.

Required Gets or sets a value indicating whether the argument is required when its parent command is invoked. Default is auto-detected.

An option/argument will be considered required when

  • There is no property initializer and the property type is a reference type (e.g. public string Arg { get; set; }). string is a reference type which has a null as the default value but bool and enum are value types which already have non-null default values. Nullable<T> is a reference type, e.g. bool?.
  • There is a property initializer, but it's initialized with null or null! (SuppressNullableWarningExpression) (e.g. public string Arg { get; set; } = null!;).
  • If it's forced via attribute property Required (e.g. [CliArgument(Required = true)]).
  • If it's forced via required modifier (e.g. public required string Opt { get; set; }). Note that for being able to use required modifier, if your target framework is below net7.0, you also need <LangVersion>11.0</LangVersion> tag (minimum) in your .csproj file (our source generator supplies the polyfills automatically as long as you set C# language version to 11).

An option/argument will be considered optional when

  • There is no property initializer (e.g. public bool Opt { get; set; }) but the property type is a value type which already have non-null default value.
  • There is a property initializer, and it's not initialized with null or null! (SuppressNullableWarningExpression) (e.g. public string Arg { get; set; } = "Default";).
  • If it's forced via attribute property Required (e.g. [CliArgument(Required = false)]).

When an argument is required, the argument has to be specified on the command line and if its parent command is invoked without it, an error message is displayed and the command handler isn't called. When an argument is not required, the argument doesn't have to be specified on the command line, the default value provides the argument value.

ValidationMessageGets or sets an error message to show when ValidationPattern does not match and validation fails.
ValidationPattern Gets or sets a regular expression pattern used to determine if argument value(s) is valid.

Note that you can specify regular expression options inline in the pattern with the syntax (?imnsx-imnsx):

C#
ValidationPattern = @"(?i)^[a-z]+$"
Regular expression quick reference
Regular expression options

ValidationRules Gets or sets a set of validation rules used to determine if argument value(s) is valid.

When combining validation rules, use bitwise 'or' operator(| in C#):

C#
ValidationRules = CliValidationRules.NonExistingFile | CliValidationRules.LegalPath

See Also