Jag har skrivit en hel del program i arbetet och de allra flesta är konsolprogram, alltså program utan ett grafiskt gränssnitt.
Ganska sällan fungerar dessa utan parametrar eftersom utan parametrar blir ju programmen ganska statiska.
I Main()-proceduren får vi med oss alla parametrar som en array av string.
static void Main(string[] args)
Man kan säkert göra på en massa olika sätt, jag har vanligtvis loopat mig igenom arrayen och med en switch tilldelat olika variabler ett värde. I slutet har man kollat så att alla nödvändiga variabler har ett värde som ser hyfsat ut. Ett av problemen är t.ex. att ta hand om olika sätt att presentera variablerna: -var, /var, –var, -var=value, -var:value och alla möjliga kombinationer av dessa.
Jag har nu hittat ett alternativ och en twist. Alternativet heter NDesk.Options. Det är på inget sätt nytt men det är faktiskt nytt för mig. Jag är inte van vid att söka efter ”plugins” eller vad man ska kalla det. Nå, NDesk.Options skapar förutsättningar för att hantera parametrar – argument – på ett väldigt bra sätt.
Man skapar s.k. OptionSets och när man parsar args så görs saker automagiskt i bakgrunden. Ett OptionSet skapas så här:
var p = new OptionSet () { { "n|name=", "the {NAME} of someone to greet.", v => names.Add (v) }, { "r|repeat=", "the number of {TIMES} to repeat the greeting.\n" + "this must be an integer.", (int v) => repeat = v }, { "v", "increase debug message verbosity", v => { if (v != null) ++verbosity; } }, { "h|help", "show this message and exit", v => show_help = v != null }, };
Fast – och här kommer twisten – det finns ett ännu enklare sätt. Genom att använda NDesk.Option.Extensions blir riktigt enkelt.
var ops = new OptionSet(); var names = ops.AddVariableList<string>("n|name", "Name to greet."); var greet = ops.AddVariable<string>("g|greeting", "The greeting"); var hlp = ops.AddSwitch("h|help", "Show this message.");
Förutom de tre funktionerna ovan finns även
AddVariableMatrix<T>
som returnerar en Key/Value collection. Mer hjälp kan få på deras GitHub.
NDesk.Option ordnar till det så fint att ”n|name” gör att alla kombinationer av dessa parametrar är OK utan att vi behöver bry oss om det; -n, -name –name, /n etc. Den fixar även parametervärdet, d.v.s. /n:Kalle eller –name=Kalle. Inte heller det behöver vi ta hand om själva.
En stor eloge till teamen bakom både NDesk.Options och NDesk.Options.Extensions!
Exempel:
static void Main(string[] args) { var ops = new OptionSet(); var names = ops.AddVariableList<string>("n|name", "Name to greet."); var greet = ops.AddVariable<string>("g|greeting", "The greeting"); var hlp = ops.AddSwitch("h|help", "Show this message."); var res = ops.Parse(args); if (hlp.Enabled) ShowHelp(ops); foreach(var n in names) { Console.WriteLine(string.Format("{0} {1}",greet.Value,n)); } } private static void ShowHelp(OptionSet p) { Console.WriteLine("Usage: greet [OPTIONS]+ message"); Console.WriteLine("Greet a list of individuals with an optional mes Console.WriteLine(); Console.WriteLine("Options:"); p.WriteOptionDescriptions(Console.Out); }
En smart grej här är
p.WriteOptionDescriptions(Console.Out);
Det tar med sig den andra parametern i vår .AddVariable<>(); så man behöver inte hantera det i sin hjälpprocedur.