问题:
需要应用程序以标准格式(在1.5.3中介绍)接受一个或多个命令行参数。你需要访问和解析传递给应用程序的完整的命令行。
解决方案:
在例1-5中,结合使用以下类来帮助解析命令行参数:Argument\ArgumentDefinition和ArgumentSemanticAnalyzer。
例1-5:Argument类:
using System;
using System.Diagnostics;
using System.Linq;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;
public sealed class Argument
{
public string Original { get; }
public string Switch { get; private set; }
public ReadOnlyCollection<string> SubArguments { get; }
private List<string> subArguments;
public Argument(string original)
{
Original = original; Switch = string.Empty;
subArguments = new List<string>();
SubArguments = new ReadOnlyCollection<string>(subArguments);
Parse();
}
private void Parse()
{
if (string.IsNullOrEmpty(Original))
{
return;
}
char[] switchChars = { '/', '-' };
if (!switchChars.Contains(Original[0]))
{
return;
}
string switchString = Original.Substring(1);
string subArgsString = string.Empty;
int colon = switchString.IndexOf(':');
if (colon >= 0)
{
subArgsString = switchString.Substring(colon + 1);
switchString = switchString.Substring(0, colon);
}
Switch = switchString;
if (!string.IsNullOrEmpty(subArgsString))
subArguments.AddRange(subArgsString.Split(';'));
}
// 一组谓词,提供关于参数的有用信息
// 使用lambda表达式实现
public bool IsSimple => SubArguments.Count == 0;
public bool IsSimpleSwitch =>
!string.IsNullOrEmpty(Switch) && SubArguments.Count == 0;
public bool IsCompoundSwitch => !string.IsNullOrEmpty(Switch) && SubArguments.Count == 1;
public bool IsComplexSwitch => !string.IsNullOrEmpty(Switch) && SubArguments.Count > 0;
}
public sealed class ArgumentDefinition
{
public string ArgumentSwitch { get; }
public string Syntax { get; }
public string Description { get; }
public Func<Argument, bool> Verifier { get; }
public ArgumentDefinition(string argumentSwitch, string syntax, string description, Func<Argument, bool> verifier)
{
ArgumentSwitch = argumentSwitch.ToUpper();
Syntax = syntax;
Description = description;
Verifier = verifier;
}
public bool Verify(Argument arg) => Verifier(arg);
}
public sealed class ArgumentSemanticAnalyzer
{
private List<ArgumentDefinition> argumentDefinitions = new List<ArgumentDefinition>();
private Dictionary<string, Action<Argument>> argumentActions = new Dictionary<string, Action<Argument>>();
public ReadOnlyCollection<Argument> UnrecognizedArguments { get; private set; }
public ReadOnlyCollection<Argument> MalformedArguments { get; private set; }
public ReadOnlyCollection<Argument> RepeatedArguments { get; private set; }
public ReadOnlyCollection<ArgumentDefinition> ArgumentDefinitions =>
new ReadOnlyCollection<ArgumentDefinition>(argumentDefinitions);
public IEnumerable<string> DefinedSwitches => from argumentDefinition in argumentDefinitions select argumentDefinition.ArgumentSwitch;
public void AddArgumentVerifier(ArgumentDefinition verifier) => argumentDefinitions.Add(verifier);
public void RemoveArgumentVerifier(ArgumentDefinition verifier)
{
var verifiersToRemove = from v in argumentDefinitions
where v.ArgumentSwitch == verifier.ArgumentSwitch
select v;
foreach (var v in verifiersToRemove)
argumentDefinitions.Remove(v)