Last active
May 9, 2020 23:16
-
-
Save pwhe23/ec65b53db9e33a5df1f93fe72d50e9af to your computer and use it in GitHub Desktop.
System.CommandLine ConfigureFromClass example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Nuget: System.CommandLine | |
| //Nuget: System.ComponentModel.Annotations | |
| using System; | |
| using System.CommandLine; | |
| using System.CommandLine.Binding; | |
| using System.CommandLine.Invocation; | |
| using System.ComponentModel; | |
| using System.ComponentModel.DataAnnotations; | |
| using System.Linq; | |
| using System.Reflection; | |
| public static class Program | |
| { | |
| public static int Main(string[] args) | |
| { | |
| args = new string[] { | |
| "-Name", "Paul", | |
| "-Message", "Hello {0}!", | |
| }; | |
| var command = new RootCommand(); | |
| command.ConfigureFromClass<Hello>(hello => | |
| { | |
| Console.WriteLine(hello.Speak()); | |
| }); | |
| return command.Invoke(args); | |
| } | |
| } | |
| [Description("Say Hello")] | |
| public class Hello | |
| { | |
| [Description("Someone's name")] | |
| public string Name { get; set; } | |
| [Description("A simple message"), Required] | |
| public string Message { get; set; } | |
| public string Speak() | |
| { | |
| return string.Format(Message, Name); | |
| } | |
| }; | |
| public static class Extensions | |
| { | |
| public static void ConfigureFromClass<T>(this Command command, Action<T> execute) | |
| where T : new() | |
| { | |
| var commandType = typeof(T); | |
| command.Description = commandType | |
| .GetCustomAttributes() | |
| .OfType<DescriptionAttribute>() | |
| .FirstOrDefault() | |
| ?.Description; | |
| var props = commandType.GetProperties(); | |
| foreach (var prop in props) | |
| { | |
| var description = prop.GetAttribute<DescriptionAttribute>()?.Description; | |
| var required = prop.GetAttribute<RequiredAttribute>() != null; | |
| var option = new Option($"-{prop.Name}", description) | |
| { | |
| Required = required, | |
| }; | |
| option.Argument = new Argument | |
| { | |
| ArgumentType = prop.PropertyType, | |
| }; | |
| command.AddOption(option); | |
| } | |
| command.Handler = CommandHandler.Create((InvocationContext context) => | |
| { | |
| var modelBinder = new ModelBinder<T>(); | |
| var cmd = new T(); | |
| modelBinder.UpdateInstance(cmd, context.BindingContext); | |
| execute(cmd); | |
| }); | |
| } | |
| private static T GetAttribute<T>(this PropertyInfo prop, bool inherit = true) | |
| { | |
| return prop | |
| .GetCustomAttributes(inherit) | |
| .OfType<T>() | |
| .FirstOrDefault(); | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment