Settembre 2016

Volume 31 Numero 9

Il presente articolo è stato tradotto automaticamente.

Essential .NET - Elaborazione dalla riga di comando con .NET Core 1.0

Da Mark Michaelis

Mark MichaelisNella colonna .NET essenziale di questo mese, è possibile continuare la ricerca avviata in varie funzionalità di .NET Core, questa volta con una versione completa (non è più in versione beta o una euphemistic versione release candidate). In particolare, mi occuperò di concentrarsi su relative utilità da riga di comando (che si trovano all'interno della libreria .NET Core comuni in github.com/aspnet/Common) e come sfruttarle per l'analisi di una riga di comando. Confessare che mi emoziona particolarmente l'infine vedere supporto di analisi della riga di comando integrato in .NET Core come se fosse qualcosa che ho desiderato per partire da .NET Framework 1.0. Spero che una raccolta predefinita di .NET Core può essere utile standardizzare, anche se solo leggermente, il formato della riga di comando/struttura tra programmi. Non è così importante per me lo standard novità quanto vi essere una convenzione che gli utenti per impostazione predefinita, anziché tutti gli utenti di creare i propri.

Una convenzione della riga di comando

La maggior parte delle funzionalità della riga di comando si trova all'interno del pacchetto Microsoft.Extensions.CommandLineUtils NuGet. Inclusi nell'assembly è una classe CommandLineApplication che consente l'analisi della riga di comando con il supporto per i nomi lunghi e brevi per le opzioni, assegnati valori (uno o più) con un virgola o uguale a un accesso e i simboli come-? Per assistenza. A proposito della Guida in linea, la classe include il supporto per la visualizzazione automaticamente il testo della Guida. Figura 1 illustra alcune righe di comando di esempio che sarebbe supportati.

Figura 1 righe di comando di esempio

Options (Opzioni) Program.exe -f = Inigo, -l Montoya – hello – nomi Princess – nomi Buttercup

Opzione -f con valore "Inigo"

Opzione -l con valore "Montoya"

Opzione – hello con valore "on"

Opzione-i nomi con i valori "La Principessa" e "Buttercup"

Comandi con argomenti Program.exe "hello", "Inigo", "Montoya", "It", "is", "a", "piacere", "a", "soddisfare", "è".

Comando "hello"

Argomento "Inigo"

Argomento "Montoya"

Argomento Greetings con i valori ",""è", "a", "unità da," "a", "soddisfare", "si."

Simboli Program.exe-? Visualizzare la Guida

 

Come descritto di seguito, sono disponibili più tipi di argomenti, uno dei quali è denominato "Argomento". L'overload dell'argomento del termine da fare riferimento ai valori specificati nella riga di comando e i dati di configurazione della riga di comando può comportare problemi di ambiguità significativi. Pertanto, per il resto dell'articolo, sarà distinguere tra un argomento generico di qualsiasi tipo, specificato dopo il nome del file eseguibile, e il tipo di argomento denominato "Argomento" (maiuscole) per le maiuscole e minuscole. Allo stesso modo, non è necessario distinguere altri tipi di argomento, opzione e comando, utilizzando iniziali maiuscole anziché i termini minuscoli genericamente all'argomento. Prendere nota di questo, come sarà importante in tutto il resto dell'articolo.

Ciascuno dei tipi di argomento viene descritto come segue:

  • Opzioni: Le opzioni vengono identificate con un nome, in cui il nome è preceduto da un singolo (-) o doppio trattino (-). I nomi delle opzioni a livello di codice vengono definiti utilizzando i modelli e un modello può includere uno o più di tre indicatori seguenti: breve nome, il nome lungo, simbolo. Inoltre, un'opzione potrebbe essere associato un valore. Ad esempio, potrebbe essere un modello "-n | -nome | -n < nome > "che consente l'opzione nome completo per essere identificato da uno qualsiasi degli tre indicatori. (Tuttavia, il modello non è necessario tutti e tre gli identificatori.) Si noti che l'utilizzo di un trattino singolo o doppio che determina se viene specificato un nome breve o lungo, indipendentemente dalla lunghezza effettiva del nome.
    Per associare un valore a un'opzione, è possibile utilizzare uno spazio o l'operatore di assegnazione (=). -f = Inigo e -l Montoya, pertanto, sono entrambi gli esempi di specificare un valore di opzione.
    Se i numeri vengono utilizzati nel modello, saranno parte dei nomi brevi o lunghi, non il simbolo.
  • Argomenti: Gli argomenti vengono identificati in base all'ordine in cui appaiono piuttosto che da un nome. Pertanto, un valore nella riga di comando che non è preceduto da un nome di opzione è un argomento. Il valore corrisponde all'argomento è in base all'ordine in cui è presente (opzioni e i comandi vengono escluse nel conteggio).
  • Comandi: Comandi forniscono un raggruppamento di argomenti e le opzioni. Ad esempio, è possibile configurare un comando nome "hello" seguita da una combinazione di argomenti e opzioni (o persino sottocomandi). I comandi sono identificati da una parola chiave configurata, il nome del comando, che raggruppa tutti i valori dopo il nome del comando da parte della definizione del comando.

Configurare la riga di comando

Dopo che fa riferimento il Microsoft.Extensions.CommandLineUtils Core .NET inizia con la classe CommandLineApplication di programmazione la riga di comando. Questa classe è in grado di configurare ogni comando, l'opzione e l'argomento. Quando si crea un'istanza di CommandLineApplication, il costruttore dispone di un valore booleano facoltativo che consente di configurare la riga di comando per generare un'eccezione (impostazione predefinita), se viene visualizzato un argomento che non è stata configurata in modo specifico.

Data un'istanza di CommandLineApplication, configurare gli argomenti utilizzando i metodi di opzione, argomento e comando. Si supponga, ad esempio, che si desidera supportare una sintassi della riga di comando come indicato di seguito, dove gli elementi racchiusa tra parentesi quadre sono facoltativi e parentesi angolari sono i valori specificati dall'utente o gli argomenti:

Program.exe <-g|--greeting|-$ <greeting>> [name <fullname>] 
     [-?|-h|--help] [-u|--uppercase]

Figura 2 configura la funzionalità di analisi di base.

Figura 2 configurazione la riga di comando

public static void Main(params string[] args)
{
    // Program.exe <-g|--greeting|-$ <greeting>> [name <fullname>]
    // [-?|-h|--help] [-u|--uppercase]
  CommandLineApplication commandLineApplication =
    new CommandLineApplication(throwOnUnexpectedArg: false);
  CommandArgument names = null;
  commandLineApplication.Command("name",
    (target) =>
      names = target.Argument(
        "fullname",
        "Enter the full name of the person to be greeted.",
        multipleValues: true));
  CommandOption greeting = commandLineApplication.Option(
    "-$|-g |--greeting <greeting>",
    "The greeting to display. The greeting supports"
    + " a format string where {fullname} will be "
    + "substituted with the full name.",
    CommandOptionType.SingleValue);
  CommandOption uppercase = commandLineApplication.Option(
    "-u | --uppercase", "Display the greeting in uppercase.",
    CommandOptionType.NoValue);
  commandLineApplication.HelpOption("-? | -h | --help");
  commandLineApplication.OnExecute(() =>
  {
    if (greeting.HasValue())
    {
      Greet(greeting.Value(), names.Values, uppercase.HasValue());
    }
    return 0;
  });
  commandLineApplication.Execute(args);
}
private static void Greet(
  string greeting, IEnumerable<string> values, bool useUppercase)
{
  Console.WriteLine(greeting);
}

Inizia con CommandLineApplication

Per iniziare, creare l'istanza di CommandLineApplication, che specifica se l'analisi della riga di comando verrà strict, throwOnUnexpectedArg è true, o Media. Se specifica per generare un'eccezione quando non è previsto un argomento, tutti gli argomenti dovrà essere configurato in modo esplicito. In alternativa, se throwOnUnexpectedArg è false, quindi gli eventuali argomenti non sono riconosciuti dalla configurazione verranno archiviati nel campo CommandLineApplication.RemainingArguments.

Configurazione di un comando e il relativo argomento

Il passaggio successivo in Figura 2 sta configurando il comando "nome". La parola chiave che identifica il comando all'interno di un elenco di argomenti è il primo parametro della funzione di comando, nome. Il secondo parametro è un delegato Action < CommandLineApplication > configurazione, in cui tutti gli argomenti secondari del nome del comando configurati. In questo caso, è presente solo uno, un argomento di tipo CommandArgument con il nome della variabile di "greeting". Tuttavia, è possibile aggiungere ulteriori argomenti, le opzioni e comandi secondari anche all'interno del delegato di configurazione. Inoltre, il parametro di destinazione del delegato, un CommandLineApplication, ha una proprietà padre che punta a commandLineArgument, ovvero l'elemento padre viene configurato CommandLineArgument di destinazione in cui il nome del comando.

Si noti che nella configurazione di nomi di argomento I identifica in modo specifico che supporterà multipleValues. In questo modo, consente di specificare più di un valore, più nomi in questo caso. Ognuno di questi valori viene visualizzata dopo l'identificatore dell'argomento "nome" finché non viene visualizzato un altro identificatore di argomento o opzione. I primi due parametri di funzione con argomenti sono nome, il riferimento al nome dell'argomento in modo da poterla identificare in un elenco di argomenti e la descrizione.

Un ultimo aspetto da segnalare la configurazione del nome di comando è il fatto che è necessario salvare il valore restituito dalla funzione con argomenti (e la funzione di opzione eventuale). Ciò è necessario in un secondo momento è possibile recuperare gli argomenti associati i nomi di argomento. Senza salvare un riferimento, si otterrà in cui cercare il commandLineApplication.Commands[0]. Raccolta di argomenti per recuperare i dati dell'argomento.

Un modo elegante per salvare tutti i dati della riga di comando è inserirla in una classe separata che è decorata con gli attributi da repository Scaffolding Progettoasp.NET (github.com/aspnet/Scaffolding), in particolare la cartella src/Microsoft.VisualStudio.Web.CodeGeneration.Core/CommandLine. Per ulteriori informazioni, vedere "Implementazione di una riga di comando classe con .NET Core" (bit.ly/296SluA).

Un'opzione di configurazione

L'argomento successivo configurato in Figura 2 è il saluto opzione, è di tipo OpzioneComando. Configurazione di un'opzione viene eseguita tramite la funzione di opzione, in cui il primo parametro è un parametro di stringa del modello. Si noti che è possibile specificare diversi nomi (per esempio, -$, -g e - saluto) per l'opzione e ciascuno di essi verrà utilizzati per identificare l'opzione dall'elenco di argomenti. Inoltre, un modello può facoltativamente specificare un valore associato tramite un nome racchiusi tra parentesi quadre angolo segue gli identificatori di opzione. Dopo il parametro description, la funzione di opzione include un parametro CommandOptionType obbligatorio. Questa opzione identifica:

  1. Se qualsiasi valore può essere specificato dopo l'identificatore di opzione. Se viene specificato un CommandOptionType di NoValue, quindi la funzione CommandOption.Value verrà impostata su "attivato" se l'opzione viene visualizzata all'interno dell'elenco di argomenti. Il valore "on" viene restituito anche se viene specificato un valore diverso dopo l'identificatore di opzione e, infatti, se viene specificato un valore. Per visualizzare un esempio, esaminare l'opzione maiuscolo in Figura 2.
  2. In alternativa, se il CommandOptionType è SingleValue e viene visualizzato alcun valore, verrà generata una CommandParsingException ma viene specificato l'identificatore di opzione che identifica l'opzione non è stata identificata, perché non ha soddisfatto del modello. In altre parole, SingleValue consente di controllare che il valore viene fornito, presupponendo che l'identificatore di opzione non viene visualizzato.
  3. Infine, è possibile fornire un CommandOptionType di MultipleValue. A differenza dei valori più associati a un comando, tuttavia, più valori nel caso di un'opzione consentono la stessa opzione specificare più volte. Ad esempio, program.exe-nome Inigo-nome Montoya.

Si noti che nessuna delle opzioni di configurazione verrà configurato in modo l'opzione è obbligatoria. E, in effetti, lo stesso vale per un argomento. Per generato un errore se non è specificato un valore, è necessario controllare se la funzione HasValue segnala un errore se viene restituito false. Nel caso di una serie di CommandArgument, la proprietà Value restituirà null se viene specificato alcun valore. Per segnalare l'errore, prendere in considerazione la visualizzazione di un messaggio di errore aggiungendo il testo della Guida in modo gli utenti dispongono di informazioni necessarie per risolvere il problema.

Un'altra funzionalità importante di CommandLineApplication meccanismo di analisi consiste nella distinzione maiuscole/minuscole. E, in realtà, in questo momento non è semplice configurazione che consente di renderlo tra maiuscole e minuscole. Pertanto, sarà necessario cambiare il gli effettivi argomenti passati al CommandLineApplication (tramite il metodo Execute, come illustrerò tra poco) prima di raggiungere tra maiuscole e minuscole. (In alternativa, è possibile tentare di inviare una richiesta di pull github.com/aspnet/Common per abilitare questa opzione.)

Visualizzare la Guida e versione

Incorporata di CommandLineApplication è una funzione ShowHelp che visualizza il testo della Guida associato automaticamente alla configurazione della riga di comando. Ad esempio, Figura 3 viene illustrato l'output ShowHelp per Figura 2.

Figura 3 visualizzazione ShowHelp Output

Usage:  [options] [command]
Options:
  -$|-g |--greeting <greeting>  The greeting to display. 
                                The greeting supports a format string 
                                where {fullname} will be substituted 
                                with the full name.
  -u | --uppercase              Display the greeting in uppercase.
  -? | -h | --help              Show help information
Commands:
  name 
Use " [command] --help" for more information about a command.

Sfortunatamente, la Guida visualizzata non identifica se un'opzione o comando è, infatti, facoltativo. In altre parole, il testo della Guida si presuppone che e Visualizza (tramite le parentesi quadre) che tutte le opzioni e i comandi sono facoltativi.

Sebbene sia possibile chiamare ShowHelp in modo esplicito, ad esempio quando si gestisce un errore della riga di comando personalizzato, si viene automaticamente richiamato ogni volta che viene specificato un argomento corrisponda al modello HelpOption. E il modello HelpOption specificato tramite un argomento del metodo CommandLineApplication.HelpOption.

Analogamente, esiste un metodo ShowVersion per visualizzare la versione dell'applicazione. Ad esempio ShowHelp, è configurato tramite uno dei due metodi:

public CommandOption VersionOption(
  string template, string shortFormVersion, string longFormVersion = null).
public CommandOption VersionOption(
  string template, Func<string> shortFormVersionGetter,
  Func<string> longFormVersionGetter = null)

Si noti che entrambi i metodi richiedono le informazioni sulla versione che si desidera visualizzare per essere specificato nella chiamata a VerisionOption.

L'analisi e la lettura dei dati della riga di comando

Finora è stato rivisto in modo dettagliato come configurare il CommandLineApplication, ma non ancora trattato il processo mai in modo-critico di attivare l'analisi della riga di comando o che cosa accadrà immediatamente dopo la chiamata di analisi.

Per attivare l'analisi della riga di comando che è necessario richiamare la funzione CommandLineApplication.Execute e passare l'elenco di argomenti specificato nella riga di comando. In Figura 1, gli argomenti vengono specificati nel parametro argomenti del metodo Main in modo che in passato alla funzione Execute direttamente (ricordare di gestire prima maiuscole e minuscole se non è auspicabile distinzione maiuscole/minuscole). È il metodo Execute che imposta i dati della riga di comando associati a ogni argomento e l'opzione che è configurato.

Si noti che CommandLineAppliction include un OnExecute (Func < int > invoke) funzione in cui è possibile passare un delegato Func < int > che verrà eseguita automaticamente una volta durante l'analisi viene completata. In Figura 2, al metodo OnExecute accetta un delegato di tipo semplice che verifica che sia stato specificato il comando greet prima di richiamare una funzione Greet.

Si noti inoltre che il int restituito dal delegato invoke è progettato come consente di specificare un valore restituito dal metodo Main. E, in realtà, il valore restituito da invoke corrisponderà al valore restituito dall'esecuzione. Poiché l'analisi viene considerato un'operazione relativamente lenta (Suppongo che il relativo tutti), Execute supporta inoltre un overload che accetta un Func < < int >> di attività, consentendo una chiamata asincrona dell'analisi della riga di comando.

Linee guida: Comandi, argomenti e opzioni

Dato i tipi di tre comandi disponibili, è opportuno valutare rapidamente protocollo da usare.

Si utilizzare i comandi durante la compilazione semanticamente identificazione un'azione, ad esempio, importare o eseguire il backup.

Si utilizzare le opzioni per consentire al programma di informazioni di configurazione come intero o un comando specifico.

Ottimizza per un verbo per il nome di un comando e un aggettivo o sostantivo per il nome di un'opzione (colore, ad esempio-, - parallela, - projectname).

Indipendentemente dal quale tipo di argomento configurare, considerare le linee guida seguenti:

Si esaminare nel caso dei nomi degli identificatori di argomento. È possibile generare molta confusione per gli utenti che consente di specificare FullName - o - fullname quando la riga di comando esegue la ricerca di una combinazione diversa.

Si scrivere test per l'analisi della riga di comando. Metodi Execute e OnExecute rendono questo relativamente facile.

Si utilizzare argomenti quando l'individuazione di determinati argomenti in base al nome è complessa o quando sono consentiti più valori, ma facendolo precedere ciascuno con un identificatore di opzione è difficile da gestire.

Provare sfruttando IntelliTect.AssertConsole (itl.tc/CommandLineUtils) per il reindirizzamento console input e output per inserire e acquisire la console in modo da poterlo verificare.

È un possibile svantaggio CommandLineUtils di base di .NET e che sono basate su inglese e non localizzato. Testo visualizzato ad esempio quelle disponibili in ShowHelp (insieme ai messaggi di eccezione che in genere non sono localizzati) sono tutti in inglese. In genere, ciò potrebbe non essere un problema ma perché una riga di comando fa parte di un'interfaccia con l'utente, esistono probabilmente scenari in cui solo in lingua inglese è accettabile. Per questo motivo:

Provare la scrittura di funzioni personalizzate per ShowHelp e ShowHint se la localizzazione è importante.

Si controllare CommandLineApplication.RemainingArguments quando il CommandLineApplication è configurato per non generare eccezioni (throwOnUnexpectedArg = false).

Conclusioni

Negli ultimi tre anni di .NET Framework ha subito alcune transizioni principali:

  • È incluso il supporto multipiattaforma, incluso il supporto per iOS, Android e Linux, Wow.
  • È eseguita la migrazione da un approccio proprietario secret verso lo sviluppo a un completamente aperto, aprire database di origine, modulo.
  • Si è verificato un significativo il refactoring delle API BCL per la libreria Standard di .NET in una piattaforma estremamente modulare (incrociata) che può essere sfruttata tramite la vasta gamma di tipi di applicazioni, se il Software come un servizio mobile, in locale, Internet of Things, desktop e altro ancora.
  • Si è verificato un rebirth di .NET, seguendo l'era di Windows 8 in cui è stata ignorata con poche strategia o roadmap di nota.

Vale a dire, se è stato ancora avviata di nuovo .NET Core 1.0, ora è giunto il momento di eseguire questa operazione, consentendo l'intervallo di tempo più lungo in cui si desidera ammortizzare la curva di apprendimento. In altre parole, se si stia valutando l'aggiornamento da versioni precedenti, farlo ora. Ci sono buone verrà eseguito l'aggiornamento a un certo punto e prima eseguire probabilità, prima di sfruttare le nuove funzionalità.


Mark Michaelis è fondatore di IntelliTect, dove ha serve come responsabile dell'architettura tecnico e istruttore.  Per quasi due decenni lavora un Microsoft MVP e un Microsoft Regional Director poiché 2007. Michaelis viene utilizzato in diversi software progettazione revisione team Microsoft, tra cui c#, Microsoft Azure, SharePoint e Visual Studio ALM. Ha come relatore a conferenze per gli sviluppatori e ha scritto numerosi libri, tra cui il suo più recente, "Essential c# 6.0 (5 ° edizione)" (itl.tc/EssentialCSharp). È possibile contattarlo su Facebook al facebook.com/Mark.Michaelis, sul suo blog all'indirizzo IntelliTect.com/Mark, su Twitter: @markmichaelis o tramite posta elettronica all'indirizzo mark@IntelliTect.com.

Grazie per i seguenti esperti tecnici IntelliTect per la revisione dell'articolo: Phil Spokas e Michael Stokesbary