Skip to content

Instantly share code, notes, and snippets.

@robertkruis
Last active August 3, 2016 11:33
Show Gist options
  • Save robertkruis/82b794ded5d16a390d89eb2071035388 to your computer and use it in GitHub Desktop.
Save robertkruis/82b794ded5d16a390d89eb2071035388 to your computer and use it in GitHub Desktop.
CommandLine: Display help text without ParseArguments call using reflection
class Options
{
[Option('i', "install",
HelpText = "Installs the given packages into the project.")]
public IEnumerable<string> Packages { get; set; }
}
static class ParserResultExtensions
{
/// <summary>
/// Gets the AutoBuild help text from the result.
/// </summary>
/// <typeparam name="T">The type of options</typeparam>
/// <returns>The AutoBuild help text in its string representation, or an empty string.</returns>
public static string GetAutoBuildHelpText<T>(this ParserResult<T> result)
{
var typeInfo = GetTypeInfoInstance<T>();
if (typeInfo != null)
{
var notParsed = GetNotParsedInstanceAs<T>(typeInfo, Enumerable.Empty<Error>());
if (notParsed != null)
{
return HelpText
.AutoBuild(notParsed)
.ToString();
}
}
return string.Empty;
}
private static object GetTypeInfoInstance<T>()
{
return Type
.GetType($"{CommandLineTypeInfoTypeName},{CommandLineAssembly}")
?.GetMethod(CommandLineTypeInfoCreateMethodName, CommandLineTypeInfoCreateArgumentTypes)
?.Invoke(null, new object[] { typeof(T) });
}
private static ParserResult<T> GetNotParsedInstanceAs<T>(object typeInfo, IEnumerable<Error> errors)
{
return Type
.GetType($"{CommandLineNotParsedTypeName},{CommandLineAssembly}")
?.MakeGenericType(typeof(T))
?.GetTypeInfo()
?.DeclaredConstructors
?.First()
?.Invoke(new object[] { typeInfo, errors }) as ParserResult<T>;
}
private const string CommandLineAssembly = "CommandLine";
private const string CommandLineTypeInfoTypeName = "CommandLine.TypeInfo";
private const string CommandLineNotParsedTypeName = "CommandLine.NotParsed`1";
private const string CommandLineTypeInfoCreateMethodName = "Create";
private static readonly Type[] CommandLineTypeInfoCreateArgumentTypes = new Type[] { typeof(Type) };
}
enum ExitCode : int
{
Standard = 0,
Error = 1
}
class Program
{
static int Main(string[] args)
{
var result = CommandLine.Parser.Default.ParseArguments<Options>(args);
var exitCode = result.MapResult(
options =>
{
if (options.Packages.Count() == 0)
{
Console.WriteLine(result.GetAutoBuildHelpText());
return (int)ExitCode.Error;
}
return (int)ExitCode.Standard;
},
errors =>
{
return (int)ExitCode.Error;
}
);
return exitCode;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment