O SysCommand
é um poderoso framework, multiplataforma, para desenvolver Console Applications
em .NET. É simples, fortemente tipado e com grandes influências do padrão MVC.
netstandard2.0+ | net461+ |
---|---|
A partir da versão 2.0.0, apenas os novos frameworks serão suportados, veja abaixo a tabela de suporte:
Frameworks | Versão compatível | Notas da versão |
---|---|---|
netstandard2.0, net461 | ||
netstandard1.6, net452 |
Via NuGet:
Install-Package SysCommand
Ele funciona como um analisador automatizado de linha de comando, permitindo que o programador se concentre nas regras de negócios de sua aplicação.
Para isso, você pode escolher 3 maneiras de trabalho:
- Método Main tipado: Equivale ao modelo tradicional
Main(string[] args)
, mas de forma tipada. - Propriedades: Cada propriedade será transformada em argumentos.
- Métodos: Cada método será transformado em um sub-comando: Ação
Além disso, ele dispõe de um recurso para simular um prompt de comando dentro do proprio Visual Studio, eliminando a necessidade de testar sua aplicação fora do ambiente de desenvolvimento.
Outros recursos essênciais como help
, verbose
, error handling
e outros também são suportados.
Exemplo de Main-typed
:
namespace Example.Initialization.Simple
{
using SysCommand.ConsoleApp;
public class Program
{
public static int Main(string[] args)
{
return App.RunApplication();
}
}
// Classes inheriting from `Command` will be automatically found by the system
// and its public properties and methods will be available for use.
public class MyCommand : Command
{
// This signature "Main(...)" is reserved to process arguments fastly.
public void Main(string myArgument, int? myArgument2 = null)
{
// this arg is obrigatory
this.App.Console.Write(string.Format("myArgument='{0}'", myArgument));
// verify if property was inputed by user.
if (myArgument2 != null)
this.App.Console.Write(string.Format("myArgument2='{0}'", myArgument2));
}
}
}
Testes em um prompt externo:
C:\Users\MyUser> MyApp.exe help
... the automatic help text will be shown ...
C:\Users\MyUser> MyApp.exe --my-argument "value"
myArgument='value'
C:\Users\MyUser> MyApp.exe --my-argument "value" --my-argument2 1000
myArgument='value'
myArgument2='1000'
Testes no Visual Studio usando o simulador de console:
cmd> help
... the automatic help text will be shown ...
cmd> --my-argument "value"
myArgument='value'
cmd> --my-argument "value" --my-argument2 1000
myArgument='value'
myArgument2='1000'
Exemplo de uso com propriedades:
namespace Example.Initialization.Simple
{
using SysCommand.ConsoleApp;
public class Program
{
public static int Main(string[] args)
{
return App.RunApplication();
}
}
public class MyCommand : Command
{
public string MyArgument { get; set; }
// This signature "Main()" is reserved to process properties.
public void Main()
{
if (MyArgument != null)
this.App.Console.Write(string.Format("Main MyArgument='{0}'", MyArgument));
}
}
}
cmd> --my-argument value
Main MyArgument='value'
Exemplo de ações:
namespace Example.Initialization.Simple
{
using SysCommand.ConsoleApp;
public class Program
{
public static int Main(string[] args)
{
return App.RunApplication();
}
}
public class MyCommand : Command
{
public void MyAction(bool a)
{
this.App.Console.Write(string.Format("MyAction a='{0}'", a));
}
}
}
cmd> my-action -a
MyAction a='True'
Note que não existe nenhum código de analise em nenhum exemplo, seu código está limpo e pronto para receber comandos.
Tecnicamente, existem quatro entidades de domínio que são a base do framework:
App
É o contexto da aplicação, onde uma App
contém diversos Commands
. É representada pela classe SysCommand.ConsoleApp.App
e deve ser a primeira entidade a ser configurada em seu método Main(string[] args)
.
A inicialização do contexto da aplicação pode ser feita de duas formas, por uma instância da class App
ou através do método estático App.RunApplication
que fornece um recurso de simulação de console que ajuda você a testar seus inputs dentro do próprio Visual Studio, sem a necessidade de executar seu ".exe" em um console externo, basta apertar o Play. Saiba mais: Iniciando , Inicializando com o simulador de console.
Command
Os comandos representam um agrupamento de funcionalidades do mesmo contexto de negócio, similar aos Controllers do MVC. Programaticamente eles são representadas por classes que herdam de SysCommand.ConsoleApp.Command
. Cada instância de Command
terá acesso ao contexto corrente pela propriedade this.App
.
Por padrão, o sistema tenta encontrar, de forma automática, qualquer classe que extenda de Command
, sendo assim não é necessário especifica-los na inicializaçao, embora isso seja possível. Saiba mais: Tipos de comandos , Especificando os tipos de comandos.
Argument
Os argumentos representam o meio mais básico de uma aplicação console, são os conhecidos --argument-name value
, -v
e etc. Programaticamente eles são representados pelas propriedades do Command
e devem ser acompanhados de um método chamado Main()
(sem parâmetros) para poder interceptar se uma propriedade foi ou não utilizada. O nome Main
foi escolhido pela similaridade de conceito com o método Main(string[] args)
do .NET.
Do lado do usuário, nenhuma sintaxe especial foi criada, os padrões mais conhecidos foram implementados. Os argumentos longos são acessados com o prefixo --
e são acompanhados do nome do argumento. Os argumentos curtos são acessados com um traço -
ou uma barra /
e são acompanhados de apenas um caracter. Os valores dos argumentos devem estar na frente do nome do argumento separados por um espaço
ou :
ou =
. Inputs posicionais também são suportados, possibilitando a omissão do nome do argumento.
Por padrão, todas as propriedades publicas de seu Command
serão habilitadas para serem arguments
. Saiba mais: Trabalhando com propriedades, Escolha manual de propriedades via atributo, Input, Tipos suportados.
Action
Representam ações iguais as Actions dos Controllers do MVC. Programaticamente representam os métodos do Command
e seus parâmetros (se existir) serão convertidos em arguments
e que só serão acessados quando acompanhados do nome da ação.
Seu uso é similar ao modo como usamos os recursos do git
como: git add -A
; git commit -m "comments"
, onde add
e commit
seriam o nome das ações e -A
, -m
seus respectivos argumentos.
Ainda é possível omitir o nome da ação no input do usuário. Esse recurso é chamado de Método Padrão e se assemelha muito com o uso de propriedades.
Por padrão, todos os métodos publicos de seu Command
serão habilitadas para serem actions
. Saiba mais: Trabalhando com métodos, Ignorar métodos publicos por uma escolha manual usando atributo, Métodos padrão.
Exemplo avançado:
namespace Example.Initialization.Advanced
{
using SysCommand.ConsoleApp;
using SysCommand.Mapping;
public class Program
{
public static int Main(string[] args)
{
return App.RunApplication();
// OR without "simulate console"
// var myApp = new App();
// myApp.Run(args);
// return myApp.Console.ExitCode;
}
}
public class GitCommand : Command
{
// usage:
// MyApp.exe add --all
public void Add(bool all)
{
this.App.Console.Error("Add error");
this.App.Console.Write("Add");
}
// usage:
// MyApp.exe commit -m "comments"
public void Commit(string m)
{
this.App.Console.Error("Commit error");
this.App.Console.Write("Commit");
}
}
public class MyCommand : Command
{
// "Argument without customization"
// usage:
// MyApp.exe --my-property value
public string MyProperty { get; set; }
// "Argument customized"
// usage:
// MyApp.exe --custom-property 123
// MyApp.exe -p 123
[Argument(LongName = "custom-property", ShortName = 'p', Help = "My custom argument ")]
public decimal? MyPropertyDecimal { get; set; }
// Method to process arguments/properties, if any exist.
// This signature "Main()" is reserved for this use only.
public string Main()
{
if (MyProperty != null)
this.App.Console.Write(string.Format("Main MyProperty='{0}'", MyProperty));
if (MyPropertyDecimal != null)
this.App.Console.Write(string.Format("Main MyPropertyDecimal='{0}'", MyPropertyDecimal));
return "Return methods can also be used as output";
}
// "Action without customization"
// usage:
// MyApp.exe my-action -p value
public string MyAction(string p)
{
// Example showing that properties are executed before methods
if (MyPropertyDecimal != null)
this.App.Console.Write("Use property here if you want!");
return string.Format("MyAction p='{0}'", p);
}
// "Action without customization and is a overload"
// usage:
// MyApp.exe my-action -p value --p2
public string MyAction(string p, bool p2)
{
return string.Format("MyAction p='{0}'; p2='{1}'", p, p2);
}
// "Action customized"
// usage:
// MyApp.exe custom-action
// MyApp.exe custom-action -o
[Action(Name = "custom-action", Help = "My custom action")]
public string CustomAction
(
[Argument(ShortName = 'o')]
bool? optionalParameter = null
)
{
return string.Format("MyCustomAction optionalParameter='{0}'", optionalParameter);
}
}
}
Input para exibir o help automático:
cmd> help
... show help here ...
Inputs similares ao uso do git:
cmd> add --all
Add
cmd> commit -m "comments"
Commit
Inputs com os 3 tipos de separadores de valor:
cmd> --my-property value
Main MyProperty='value'
Return methods can also be used as output
cmd> --my-property=value
Main MyProperty='value'
Return methods can also be used as output
cmd> --custom-property:123
Main MyPropertyDecimal='123'
Return methods can also be used as output
Inputs com os 2 tipos de delimitador de argumentos na forma curta:
cmd> -p 123
Main MyPropertyDecimal='123'
Return methods can also be used as output
cmd> /p 123
Main MyPropertyDecimal='123'
Return methods can also be used as output
Inputs com as 2 sobrecargas do método MyAction:
cmd> my-action -p value
MyAction p='value'
cmd> my-action -p value --p2
MyAction p='value'; p2='True'
Inputs posicionais:
cmd> my-action positional-value
MyAction p='positional-value'
cmd> my-action positional-value false
MyAction p='positional-value'; p2='False'
Inputs com parâmetros opcionais:
cmd> custom-action
MyCustomAction optionalParameter=''
cmd> custom-action -o
MyCustomAction optionalParameter='True'
Input com argumentos de diferentes comandos e com o argumento de --verbose
para permitir mostrar Erros:
cmd> commit -m "my commit" --my-property=value --custom-property:123 --verbose Error
Main MyProperty='value'
Main MyPropertyDecimal='123'
Return methods can also be used as output
Commit error
Commit
Saiba mais...
- Note que os tipos primitivos de cada propriedade estão configurados como
Nullable
. Isso é importante para ter condições de identificar que o usuário inseriu uma determinada propriedade. Saiba mais: Trabalhando com propriedades. - Todos os tipos primitivos do .NET, Enums, Enums Flags e Collections são suportados. Veja o tópico de Tipos suportados.
- Use
App.Console.Write()
,App.Console.Error()
(entre outros) para imprimir seus outputs e usufruir de recursos como overbose
. Saiba mais: Verbose. - Você pode utilizar o retorno dos métodos como
output
, inclusive o método reservadoMain()
. Ou usevoid
se não quiser usar esse recurso. Saiba mais: Output. - Se desejar, customize seus
arguments
ouactions
usando os atributosArgumentAttribute
eActionAttribute
. Você pode customizar diversos atributos como nomes, texto de ajuda e dentro outros. Saiba mais: Customizando os nomes dos argumentos e Customizando nomes de ações e argumentos. - Você pode usar métodos com o mesmo nome (sobrecargas) para definir diferentes
actions
. Elas podem ser chamadas no prompt de comando com o mesmo nome, mas os argumentos definirão qual o método a ser chamado, igual ocorre emc#
. Saiba mais: Sobrecargas - Opte por usar o método
int Program.Main(string[] args)
com retorno, assim você pode retornar o status code para o console. (ERROR=1 ou SUCCESS=0). - Existe também o suporte nativo para gerar o texto de ajuda. Saiba mais: Help.
Esse foi apenas um resumo, para conhecer mais sobre esse projeto veja a nossa Documentação.
O objetivo é ajudar programadores de qualquer linguagem de programação que sofrem para criar uma aplicação console devido a burocracia do parse e pela dificuldade de manutenção. Se você é como eu que adora criar mini-aplicações para resolver problemas do dia a dia usando consoles, então junte-se a nós!
Se você nunca trabalhou com .NET, talvez essa seja uma excelente oportunidade de conhece-lo. Com o novo .NET (Core Clr) você pode criar aplicativos em qualquer plataforma e isso pode ser simplificado com o SysCommand
.
SysCommand.dll
: Contém toda a lógica de parse e execução de linhas de comandos. Tudo foi pensado para tornar o padrão MVC tão natural quanto possível.NewtonSoft.Json
: Necessário para os recursos que fazem uso de JSON.- São dependências necessárias para o uso da sintaxe "Razor":
Microsoft.CSharp
:Microsoft.AspNetCore.Mvc.Razor.Extensions
:Microsoft.AspNetCore.Razor.Runtime
:Microsoft.Extensions.DependencyModel
:
- Criar seu projeto do tipo
Console Application
- Instale o
SysCommand
no seu projetoConsole Application
- Na primeira linha do método
public int Program.Main(string[] args)
, adicione o códigoreturn App.RunApplication()
. - Criar uma classe, em qualquer lugar, que herde de
SysCommand.ConsoleApp.Command
. - Criar suas propriedades com seus tipos
Nullable
e deixe-as como publicas. Elas se tornarãoarguments
no prompt de comando. - Crie um método
Main()
sem parâmetros em sua classe para poder interceptar os inputs de suas propriedades. UtilizeProperty != null
para identificar que a propriedade foi inserida. - Crie métodos publicos, com ou sem parâmetros, para que eles se tornem
actions
. Caso tenha parâmetros opcionais, deixe-os configurados comoNullable
pela mesma razão acima. - Digite
help
no prompt de comando que será aberto para poder visualizar suas propriedades e métodos transformados emarguments
eactions
. - Agora é só usar!
Veja a documentação completa clicando aqui
SysCommand é um projeto de código aberto. Iniciado em 2017, muitas horas foram investidos na criação e evolução deste projeto.
E tudo com apenas um objetivo: Torná-lo uma boa ferramenta para a criação de aplicativos do tipo console.. Se o SysCommand foi útil pra você, ou se você deseja ve-lo evoluir cada vez mais, considere fazer uma pequena doação (qualquer valor). Ajude-nos também com sujestões e possíveis problemas.
De qualquer forma, agradeçemos você por ter chego até aqui ;)
BitCoin:
19DmxWBNcaUGjm2PQAuMBD4Y8ZbrGyMLzK
The MIT License (MIT)
Copyright (c) 2017 Glauber Donizeti Gasparotto Junior
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.