private void AddSubcommandImpl <TSubCommand>(ConventionContext context, SubcommandAttribute subcommand) where TSubCommand : class { #pragma warning disable 618 context.Application.Command <TSubCommand>(subcommand.Name !, subcommand.Configure); #pragma warning restore 618 }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { var modelAccessor = context.ModelAccessor; if (context.ModelType == null || modelAccessor == null) { return; } const BindingFlags MethodFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; var method = context.ModelType .GetTypeInfo() .GetMethod("OnValidationError", MethodFlags); if (method == null) { return; } context.Application.ValidationErrorHandler = (v) => { var arguments = ReflectionHelper.BindParameters(method, context.Application, default); var result = method.Invoke(modelAccessor.GetModel(), arguments); if (method.ReturnType == typeof(int)) { return((int)result); } return(CommandLineApplication.ValidationErrorExitCode); }; }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var subcommandProp = context.ModelType.GetTypeInfo().GetProperty("Subcommand", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (subcommandProp == null) { return; } var setter = ReflectionHelper.GetPropertySetter(subcommandProp); context.Application.OnParsed(r => { var subCommand = r.SelectedCommand; while (subCommand != null) { if (ReferenceEquals(subCommand.Parent, context.Application)) { if (subCommand is IModelAccessor subcmdAccessor) { setter(context.ModelAccessor.GetModel(), subcmdAccessor.GetModel()); } return; } subCommand = subCommand.Parent; } }); }
public virtual void Apply(ConventionContext context) { var modelAccessor = context.ModelAccessor; if (context.ModelType == null || modelAccessor == null) { return; } var attributes = context.ModelType.GetTypeInfo().GetCustomAttributes <SubcommandAttribute>(); foreach (var attribute in attributes) { var contextArgs = new object[] { context, attribute }; foreach (var type in attribute.Types) { AssertSubcommandIsNotCycled(type, context.Application); var impl = s_addSubcommandMethod.MakeGenericMethod(type); try { impl.Invoke(this, contextArgs); } catch (TargetInvocationException ex) { // unwrap throw ex.InnerException ?? ex; } } } }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var props = ReflectionHelper.GetProperties(context.ModelType); foreach (var prop in props) { var attr = prop.GetCustomAttribute <OptionAttribute>(); if (attr == null) { continue; } EnsureDoesNotHaveHelpOptionAttribute(prop); EnsureDoesNotHaveVersionOptionAttribute(prop); EnsureDoesNotHaveArgumentAttribute(prop); var option = attr.Configure(context.Application, prop); AddOption(context, option, prop); } }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var subcommands = context.ModelType.GetTypeInfo().GetCustomAttributes <SubcommandAttribute>(); if (subcommands == null) { return; } foreach (var subcommand in subcommands) { var impl = s_addSubcommandMethod.MakeGenericMethod(subcommand.CommandType); try { impl.Invoke(this, new object[] { context, subcommand }); } catch (TargetInvocationException ex) { // unwrap throw ex.InnerException ?? ex; } } }
public virtual void Apply(ConventionContext context) { var modelAccessor = context.ModelAccessor; if (context.ModelType == null || modelAccessor == null) { return; } var parentProp = context.ModelType.GetTypeInfo().GetProperty("Parent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (parentProp == null) { return; } var setter = ReflectionHelper.GetPropertySetter(parentProp); context.Application.OnParsingComplete(r => { CommandLineApplication?subcommand = r.SelectedCommand; while (subcommand != null) { if (ReferenceEquals(context.Application, subcommand)) { if (subcommand.Parent is IModelAccessor parentAccessor) { setter(modelAccessor.GetModel(), parentAccessor.GetModel()); } return; } subcommand = subcommand.Parent; } }); }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { var modelAccessor = context.ModelAccessor; if (context.ModelType == null || modelAccessor == null) { return; } var prop = context.ModelType.GetProperty("RemainingArguments", PropertyBindingFlags); prop ??= context.ModelType.GetProperty("RemainingArgs", PropertyBindingFlags); if (prop == null) { return; } var setter = ReflectionHelper.GetPropertySetter(prop); if (prop.PropertyType == typeof(string[])) { context.Application.OnParsingComplete(r => setter(modelAccessor.GetModel(), r.SelectedCommand.RemainingArguments.ToArray())); return; } if (!typeof(IReadOnlyList <string>).IsAssignableFrom(prop.PropertyType)) { throw new InvalidOperationException(Strings.RemainingArgsPropsIsUnassignable(context.ModelType)); } context.Application.OnParsingComplete(r => setter(modelAccessor.GetModel(), r.SelectedCommand.RemainingArguments)); }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } context.Application.OnExecute(async() => await this.OnExecute(context)); }
private void AddSubcommandImpl <TSubCommand>(ConventionContext context, SubcommandAttribute subcommand) where TSubCommand : class, new() { if (context.Application.Commands.Any(c => c.Name.Equals(subcommand.Name, StringComparison.OrdinalIgnoreCase))) { throw new InvalidOperationException(Strings.DuplicateSubcommandName(subcommand.Name)); } context.Application.Command <TSubCommand>(subcommand.Name, subcommand.Configure); }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var versionOptionFromMember = context.ModelType.GetTypeInfo().GetCustomAttribute <VersionOptionFromMemberAttribute>(); versionOptionFromMember?.Configure(context.Application, context.ModelType, context.ModelAccessor.GetModel); }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var attribute = context.ModelType.GetTypeInfo().GetCustomAttribute <CommandAttribute>(); attribute?.Configure(context.Application); }
public virtual void Apply(ConventionContext context) { var modelAccessor = context.ModelAccessor; if (context.ModelType == null || modelAccessor == null) { return; } var versionOptionAttrOnType = context.ModelType.GetTypeInfo().GetCustomAttribute <VersionOptionAttribute>(); versionOptionAttrOnType?.Configure(context.Application); var props = ReflectionHelper.GetProperties(context.ModelType); VersionOptionAttribute?versionOptionAttr = null; PropertyInfo? property = null; foreach (var prop in props) { var attr = prop.GetCustomAttribute <VersionOptionAttribute>(); if (attr == null) { continue; } if (versionOptionAttr != null) { throw new InvalidOperationException(Strings.MultipleVersionOptionPropertiesFound); } if (versionOptionAttrOnType != null) { throw new InvalidOperationException(Strings.VersionOptionOnTypeAndProperty); } versionOptionAttr = attr; property = prop; EnsureDoesNotHaveOptionAttribute(prop); EnsureDoesNotHaveHelpOptionAttribute(prop); EnsureDoesNotHaveArgumentAttribute(prop); } if (versionOptionAttr == null || property == null) { return; } var option = versionOptionAttr.Configure(context.Application); AddOption(context, option, property); }
private void ApplyImpl <TModel>(ConventionContext context) where TModel : class { var constructors = typeof(TModel).GetConstructors(BindingFlags.Public | BindingFlags.Instance); var factory = FindMatchedConstructor <TModel>(constructors, context.Application, constructors.Length == 1); if (factory != null) { ((CommandLineApplication <TModel>)context.Application).ModelFactory = factory; } }
private async Task <int> OnExecute(ConventionContext context) { const BindingFlags binding = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; var typeInfo = context.ModelType.GetTypeInfo(); MethodInfo?method; MethodInfo?asyncMethod; try { method = typeInfo.GetMethod("OnExecute", binding); asyncMethod = typeInfo.GetMethod("OnExecuteAsync", binding); } catch (AmbiguousMatchException ex) { throw new InvalidOperationException(Strings.AmbiguousOnExecuteMethod, ex); } if (method != null && asyncMethod != null) { throw new InvalidOperationException(Strings.AmbiguousOnExecuteMethod); } method ??= asyncMethod; if (method == null) { throw new InvalidOperationException(Strings.NoOnExecuteMethodFound); } var arguments = ReflectionHelper.BindParameters(method, context.Application); var modelAccessor = context.ModelAccessor; if (modelAccessor == null) { throw new InvalidOperationException(Strings.ConventionRequiresModel); } var model = modelAccessor.GetModel(); if (method.ReturnType == typeof(Task) || method.ReturnType == typeof(Task <int>)) { return(await InvokeAsync(method, model, arguments)); } else if (method.ReturnType == typeof(void) || method.ReturnType == typeof(int)) { return(Invoke(method, model, arguments)); } throw new InvalidOperationException(Strings.InvalidOnExecuteReturnType(method.Name)); }
/// <inheritdoc /> public void Apply(ConventionContext context) { if (context.Application.OptionHelp != null) { return; } if (context.ModelType != null) { var typeInfo = context.ModelType.GetTypeInfo(); if (typeInfo.GetCustomAttribute <SuppressDefaultHelpOptionAttribute>() != null || typeInfo.Assembly.GetCustomAttribute <SuppressDefaultHelpOptionAttribute>() != null) { return; } } var help = new CommandOption(_template, CommandOptionType.NoValue) { Description = Strings.DefaultHelpOptionDescription, // the convention will run on each subcommand automatically. // it is better to run the command on each to check for overlap // or already set options to avoid conflict Inherited = false, }; foreach (var opt in context.Application.GetOptions()) { if (string.Equals(help.LongName, opt.LongName)) { help.LongName = null; } if (string.Equals(help.ShortName, opt.ShortName)) { help.ShortName = null; } if (string.Equals(help.SymbolName, opt.SymbolName)) { help.SymbolName = null; } } if (help.LongName != null || help.ShortName != null || help.SymbolName != null) { context.Application.OptionHelp = help; context.Application.Options.Add(help); } }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (_additionalServices != null) { context.Application.AdditionalServices = _additionalServices; } if (context.ModelType == null) { return; } s_applyMethod.MakeGenericMethod(context.ModelType).Invoke(this, new object[] { context }); }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var props = ReflectionHelper.GetProperties(context.ModelType); if (props == null) { return; } var argOrder = new SortedList <int, CommandArgument>(); var argPropOrder = new Dictionary <int, PropertyInfo>(); foreach (var prop in props) { var argumentAttr = prop.GetCustomAttribute <ArgumentAttribute>(); if (argumentAttr == null) { continue; } if (prop.GetCustomAttributes().OfType <OptionAttributeBase>().Any()) { throw new InvalidOperationException( Strings.BothOptionAndArgumentAttributesCannotBeSpecified(prop)); } AddArgument(prop, argumentAttr, context, argOrder, argPropOrder); } foreach (var arg in argOrder) { if (context.Application.Arguments.Count > 0) { var lastArg = context.Application.Arguments[context.Application.Arguments.Count - 1]; if (lastArg.MultipleValues) { throw new InvalidOperationException( Strings.OnlyLastArgumentCanAllowMultipleValues(lastArg.Name)); } } context.Application.Arguments.Add(arg.Value); } }
/// <inheritdoc /> public void Apply(ConventionContext context) { if (!string.IsNullOrEmpty(context.Application.Name)) { return; } if (context.ModelType == null) { return; } var commandName = GetCommandName(context.ModelType.Name); if (!string.IsNullOrEmpty(commandName)) { context.Application.Name = commandName; } }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.ModelType == null) { return; } var attribute = context.ModelType.GetTypeInfo().GetCustomAttribute <CommandAttribute>(); attribute?.Configure(context.Application); foreach (var subcommand in context.Application.Commands) { if (subcommand is IModelAccessor subcommandAccessor) { Apply(new ConventionContext(subcommand, subcommandAccessor.GetModelType())); } } }
/// <inheritdoc /> public virtual void Apply(ConventionContext context) { if (context.Application.Name != null) { return; } var assembly = Assembly.GetEntryAssembly(); if (assembly == null && context.ModelType != null) { assembly = context.ModelType.GetTypeInfo().Assembly; } if (assembly != null) { context.Application.Name = assembly.GetName().Name; } }
/// <inheritdoc /> public void Apply(ConventionContext context) { if (context.ModelType == null) { return; } foreach (var attr in context.ModelType.GetTypeInfo().GetCustomAttributes().OfType <IConvention>()) { attr.Apply(context); } var members = ReflectionHelper.GetMembers(context.ModelType); foreach (var member in members) { foreach (var attr in member.GetCustomAttributes().OfType <IMemberConvention>()) { attr.Apply(context, member); } } }
private void ApplyImpl <TModel>(ConventionContext context) where TModel : class { var constructors = typeof(TModel) .GetTypeInfo() .GetConstructors(BindingFlags.Public | BindingFlags.Instance); if (constructors.Length == 0) { throw new InvalidOperationException("Could not find any public constructors on " + typeof(TModel).FullName); } // find the constructor with the most parameters first foreach (var ctorCandidate in constructors.OrderByDescending(c => c.GetParameters().Count())) { var parameters = ctorCandidate.GetParameters().ToArray(); var args = new object[parameters.Length]; var matched = false; for (var i = 0; i < parameters.Length; i++) { var paramType = parameters[i].ParameterType; var service = ((IServiceProvider)context.Application).GetService(paramType); if (service == null) { break; } args[i] = service; matched = i == parameters.Length - 1; } if (matched) { (context.Application as CommandLineApplication <TModel>).ModelFactory = () => (TModel)ctorCandidate.Invoke(args); return; } } }
private void AddSubcommandImpl <TSubCommand>(ConventionContext context) where TSubCommand : class { context.Application.Command <TSubCommand>(null !, null !); // Hmm, should probably rethink this... }
private void AddArgument(PropertyInfo prop, ArgumentAttribute argumentAttr, ConventionContext convention, SortedList <int, CommandArgument> argOrder, Dictionary <int, PropertyInfo> argPropOrder) { var argument = argumentAttr.Configure(prop); foreach (var attr in prop.GetCustomAttributes().OfType <ValidationAttribute>()) { argument.Validators.Add(new AttributeValidator(attr)); } argument.MultipleValues = prop.PropertyType.IsArray || (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string)); if (argPropOrder.TryGetValue(argumentAttr.Order, out var otherProp)) { throw new InvalidOperationException( Strings.DuplicateArgumentPosition(argumentAttr.Order, prop, otherProp)); } argPropOrder.Add(argumentAttr.Order, prop); argOrder.Add(argumentAttr.Order, argument); var setter = ReflectionHelper.GetPropertySetter(prop); if (argument.MultipleValues) { convention.Application.OnParsingComplete(r => { var collectionParser = CollectionParserProvider.Default.GetParser( prop.PropertyType, convention.Application.ValueParsers); if (collectionParser == null) { throw new InvalidOperationException(Strings.CannotDetermineParserType(prop)); } if (argument.Values.Count == 0) { return; } if (r.SelectedCommand is IModelAccessor cmd) { setter.Invoke(cmd.GetModel(), collectionParser.Parse(argument.Name, argument.Values)); } }); } else { convention.Application.OnParsingComplete(r => { var parser = convention.Application.ValueParsers.GetParser(prop.PropertyType); if (parser == null) { throw new InvalidOperationException(Strings.CannotDetermineParserType(prop)); } if (argument.Values.Count == 0) { return; } if (r.SelectedCommand is IModelAccessor cmd) { setter.Invoke( cmd.GetModel(), parser.Parse( argument.Name, argument.Value, convention.Application.ValueParsers.ParseCulture)); } }); } }
private protected void AddOption(ConventionContext context, CommandOption option, PropertyInfo prop) { foreach (var attr in prop.GetCustomAttributes().OfType <ValidationAttribute>()) { option.Validators.Add(new AttributeValidator(attr)); } if (option.OptionType == CommandOptionType.NoValue && prop.PropertyType != typeof(bool)) { throw new InvalidOperationException(Strings.NoValueTypesMustBeBoolean); } if (!string.IsNullOrEmpty(option.ShortName)) { if (context.Application._shortOptions.TryGetValue(option.ShortName, out var otherProp)) { throw new InvalidOperationException( Strings.OptionNameIsAmbiguous(option.ShortName, prop, otherProp)); } context.Application._shortOptions.Add(option.ShortName, prop); } if (!string.IsNullOrEmpty(option.LongName)) { if (context.Application._longOptions.TryGetValue(option.LongName, out var otherProp)) { throw new InvalidOperationException( Strings.OptionNameIsAmbiguous(option.LongName, prop, otherProp)); } context.Application._longOptions.Add(option.LongName, prop); } var setter = ReflectionHelper.GetPropertySetter(prop); switch (option.OptionType) { case CommandOptionType.MultipleValue: var collectionParser = CollectionParserProvider.Default.GetParser(prop.PropertyType, context.Application.ValueParsers); if (collectionParser == null) { throw new InvalidOperationException(Strings.CannotDetermineParserType(prop)); } context.Application.OnParsingComplete(_ => setter.Invoke(context.ModelAccessor.GetModel(), collectionParser.Parse(option.LongName, option.Values))); break; case CommandOptionType.SingleOrNoValue: case CommandOptionType.SingleValue: var parser = context.Application.ValueParsers.GetParser(prop.PropertyType); if (parser == null) { throw new InvalidOperationException(Strings.CannotDetermineParserType(prop)); } context.Application.OnParsingComplete(_ => { if (!option.HasValue()) { return; } setter.Invoke(context.ModelAccessor.GetModel(), parser.Parse(option.LongName, option.Value(), context.Application.ValueParsers.ParseCulture)); }); break; case CommandOptionType.NoValue: context.Application.OnParsingComplete(_ => setter.Invoke(context.ModelAccessor.GetModel(), option.HasValue())); break; default: throw new NotImplementedException(); } }
private void AddSubcommandImpl <TSubCommand>(ConventionContext context) where TSubCommand : class { context.Application.Command <TSubCommand>(null, null); }
private protected void AddOption(ConventionContext context, CommandOption option, PropertyInfo prop) { var modelAccessor = context.ModelAccessor; if (modelAccessor == null) { throw new InvalidOperationException(Strings.ConventionRequiresModel); } foreach (var attr in prop.GetCustomAttributes().OfType <ValidationAttribute>()) { option.Validators.Add(new AttributeValidator(attr)); } if (option.OptionType == CommandOptionType.NoValue && prop.PropertyType != typeof(bool) && prop.PropertyType != typeof(bool?) && prop.PropertyType != typeof(bool[])) { throw new InvalidOperationException(Strings.NoValueTypesMustBeBoolean); } if (!string.IsNullOrEmpty(option.ShortName)) { if (context.Application._shortOptions.TryGetValue(option.ShortName, out var otherProp)) { throw new InvalidOperationException( Strings.OptionNameIsAmbiguous(option.ShortName, prop, otherProp)); } context.Application._shortOptions.Add(option.ShortName, prop); } if (!string.IsNullOrEmpty(option.LongName)) { if (context.Application._longOptions.TryGetValue(option.LongName, out var otherProp)) { throw new InvalidOperationException( Strings.OptionNameIsAmbiguous(option.LongName, prop, otherProp)); } context.Application._longOptions.Add(option.LongName, prop); } var getter = ReflectionHelper.GetPropertyGetter(prop); var setter = ReflectionHelper.GetPropertySetter(prop); switch (option.OptionType) { case CommandOptionType.MultipleValue: context.Application.OnParsingComplete(_ => { var collectionParser = CollectionParserProvider.Default.GetParser(prop.PropertyType, context.Application.ValueParsers); if (collectionParser == null) { throw new InvalidOperationException(Strings.CannotDetermineParserType(prop)); } if (!option.HasValue()) { if (!ReflectionHelper.IsSpecialValueTupleType(prop.PropertyType, out var type)) { if (getter.Invoke(modelAccessor.GetModel()) is IEnumerable <object> values) { foreach (var value in values) { option.TryParse(value?.ToString()); } option.DefaultValue = string.Join(", ", values.Select(x => x?.ToString())); } } } else { setter.Invoke(modelAccessor.GetModel(), collectionParser.Parse(option.LongName, option.Values)); } }); break; case CommandOptionType.SingleOrNoValue: case CommandOptionType.SingleValue: context.Application.OnParsingComplete(_ => { var parser = context.Application.ValueParsers.GetParser(prop.PropertyType); if (parser == null) { throw new InvalidOperationException(Strings.CannotDetermineParserType(prop)); } if (!option.HasValue()) { if (!ReflectionHelper.IsSpecialValueTupleType(prop.PropertyType, out var type)) { var value = getter.Invoke(modelAccessor.GetModel()); if (value != null) { option.TryParse(value.ToString()); option.DefaultValue = value.ToString(); } } } else { setter.Invoke(modelAccessor.GetModel(), parser.Parse(option.LongName, option.Value(), context.Application.ValueParsers.ParseCulture)); } }); break; case CommandOptionType.NoValue: context.Application.OnParsingComplete(_ => { if (prop.PropertyType == typeof(bool[])) { if (!option.HasValue()) { setter.Invoke(modelAccessor.GetModel(), Util.EmptyArray <bool>()); } var count = new bool[option.Values.Count]; for (var i = 0; i < count.Length; i++) { count[i] = true; } setter.Invoke(modelAccessor.GetModel(), count); } else { if (!option.HasValue()) { return; } setter.Invoke(modelAccessor.GetModel(), option.HasValue()); } }); break; default: throw new NotImplementedException(); } }