private PropertyInfo FindSpecifiedAction(Type t, ref string[] args) { var actionProperty = ArgAction.GetActionProperty(t); if (actionProperty == null) { return(null); } var specifiedAction = args.Length > 0 ? args[0] : null; if (actionProperty.Attr <ArgRequired>().PromptIfMissing&& args.Length == 0) { actionProperty.Attr <ArgRequired>().ValidateAlways(actionProperty, ref specifiedAction); args = new string[] { specifiedAction }; } if (specifiedAction == null) { return(null); } var actionArgProperty = (from p in t.GetProperties(BindingFlags.Instance | BindingFlags.Public) where p.MatchesSpecifiedAction(specifiedAction) select p).SingleOrDefault(); if (actionArgProperty == null) { throw new UnknownActionArgException("Unknown Action: " + specifiedAction); } return(actionArgProperty); }
internal static CommandLineAction Create(PropertyInfo actionProperty, List <string> knownAliases) { var ret = PropertyInitializer.CreateInstance <CommandLineAction>(); ret.ActionMethod = ArgAction.ResolveMethod(actionProperty.DeclaringType, actionProperty); ret.Source = actionProperty; ret.Arguments.AddRange(new CommandLineArgumentsDefinition(actionProperty.PropertyType).Arguments); ret.IgnoreCase = true; if (actionProperty.DeclaringType.HasAttr <ArgIgnoreCase>() && actionProperty.DeclaringType.Attr <ArgIgnoreCase>().IgnoreCase == false) { ret.IgnoreCase = false; } if (actionProperty.HasAttr <ArgIgnoreCase>() && actionProperty.Attr <ArgIgnoreCase>().IgnoreCase == false) { ret.IgnoreCase = false; } ret.Metadata.AddRange(actionProperty.Attrs <IArgMetadata>().AssertAreAllInstanceOf <ICommandLineActionMetadata>()); // This line only calls into CommandLineArgument because the code to strip 'Args' off the end of the // action property name lives here. This is a pre 2.0 hack that's only left in place to support apps that // use the 'Args' suffix pattern. ret.Aliases.AddRange(CommandLineArgument.FindDefaultShortcuts(actionProperty, knownAliases, ret.IgnoreCase)); return(ret); }
private void PopulateProperties(ArgHook.HookContext context) { context.Args.GetType().RunBeforePopulateProperties(context); foreach (PropertyInfo prop in context.Args.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) { var match = from k in context.ParserData.ExplicitParameters.Keys where prop.MatchesSpecifiedArg(k) select k; if (match.Count() > 1) { throw new DuplicateArgException("Argument specified more than once: " + prop.GetArgumentName()); } if (match.Count() == 1) { var key = match.First(); context.ArgumentValue = context.ParserData.ExplicitParameters[key]; context.ParserData.ExplicitParameters.Remove(key); } else { if (prop.HasAttr <ArgPosition>() && context.ParserData.ImplicitParameters.ContainsKey(prop.Attr <ArgPosition>().Position)) { var position = prop.Attr <ArgPosition>().Position; context.ArgumentValue = context.ParserData.ImplicitParameters[position]; context.ParserData.ImplicitParameters.Remove(position); } else { context.ArgumentValue = null; } } context.Property = prop; prop.RunBeforePopulateProperty(context); bool shouldValidateAndRevive = true; if (prop.Attr <ArgIgnoreAttribute>() != null) { shouldValidateAndRevive = false; } if (prop.IsActionArgProperty() && ArgAction.GetActionProperty(context.Args.GetType()) != null) { shouldValidateAndRevive = false; } if (shouldValidateAndRevive) { prop.Validate(context); prop.Revive(context.Args, context); } prop.RunAfterPopulateProperty(context); } context.Args.GetType().RunAfterPopulateProperties(context); }
/// <summary> /// Parses the given arguments using a command line arguments definition. The values will be populated within /// the definition. /// </summary> /// <param name="definition">The definition that defines a set of command line arguments and/or actions.</param> /// <param name="args">The command line arguments to parse</param> public static ArgAction Parse(CommandLineArgumentsDefinition definition, params string[] args) { ArgAction ret = Execute(() => { return ParseAction(definition, args); }); return ret; }
/// <summary> /// Creates a new instance of T and populates it's properties based on the given arguments. /// If T correctly implements the heuristics for Actions (or sub commands) then the complex property /// that represents the options of a sub command are also populated. /// </summary> /// <typeparam name="T">The argument scaffold type.</typeparam> /// <param name="args">The command line arguments to parse</param> /// <returns>The raw result of the parse with metadata about the specified action.</returns> public static ArgAction<T> ParseAction<T>(params string[] args) { ArgAction<T> ret = Execute<ArgAction<T>>(() => { Args instance = new Args(); return instance.ParseInternal<T>(args); }); return ret; }
/// <summary> /// Creates a new instance of the given type and populates it's properties based on the given arguments. /// If the type correctly implements the heuristics for Actions (or sub commands) then the complex property /// that represents the options of a sub command are also populated. /// </summary> /// <param name="t">The argument scaffold type.</param> /// <param name="args">The command line arguments to parse</param> /// <returns>The raw result of the parse with metadata about the specified action.</returns> public static ArgAction ParseAction(Type t, params string[] args) { ArgAction ret = Execute <ArgAction>(() => { Args instance = new Args(); return(instance.ParseInternal(t, args)); }); return(ret); }
internal static List <PropertyInfo> GetActionArgProperties(this Type t) { if (ArgAction.GetActionProperty(t) == null) { return(new List <PropertyInfo>()); } return((from prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public) where prop.IsActionArgProperty() select prop).ToList()); }
/// <summary> /// Parses the given arguments using a command line arguments definition. /// </summary> /// <param name="definition">The definition that defines a set of command line arguments and/or actions.</param> /// <param name="args">The command line arguments to parse</param> /// <returns></returns> public static ArgAction ParseAction(CommandLineArgumentsDefinition definition, params string[] args) { ArgAction ret = Execute(() => { Args instance = new Args(); return(instance.ParseInternal(definition, args)); }); return(ret); }
private static ArgAction <T> Strongify <T>(ArgAction weak) { return(new ArgAction <T>() { Args = (T)weak.Value, ActionArgs = weak.ActionArgs, ActionArgsProperty = weak.ActionArgsProperty, ActionParameters = weak.ActionParameters, ActionArgsMethod = weak.ActionArgsMethod, HandledException = weak.HandledException, Definition = weak.Definition, Context = weak.Context, Cancelled = weak.Cancelled, }); }
private static string GetShortcutInternal(PropertyInfo info, List <string> knownShortcuts) { var actionProperty = ArgAction.GetActionProperty(info.DeclaringType); if (actionProperty != null && actionProperty.Name == info.Name) { return(null); } var attr = info.Attr <ArgShortcut>(); if (attr == null) { string shortcutVal = ""; foreach (char c in info.GetArgumentName()) { shortcutVal += c; if (knownShortcuts.Contains(shortcutVal) == false) { return(shortcutVal); } } return(shortcutVal); } else { if (attr.policy.HasValue && attr.policy.Value == ArgShortcutPolicy.NoShortcut && attr.Shortcut != null) { throw new InvalidArgDefinitionException("You cannot specify a shortcut value and an ArgShortcutPolicy of NoShortcut"); } if (attr.Shortcut == null) { return(null); } if (attr.Shortcut.StartsWith("-")) { attr.Shortcut = attr.Shortcut.Substring(1); } else if (attr.Shortcut.StartsWith("/")) { attr.Shortcut = attr.Shortcut.Substring(1); } return(attr.Shortcut); } }
internal static void RegisterShortcuts(Type t, List <string> shortcuts = null) { RegisteredTypes.Add(t); bool isNested = shortcuts != null; shortcuts = isNested ? shortcuts : new List <string>(); var actionProp = ArgAction.GetActionProperty(t); foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (prop.Attr <ArgIgnoreAttribute>() != null) { continue; } if (prop.IsActionArgProperty() && actionProp != null) { continue; } var shortcut = ArgShortcut.GetShortcutInternal(prop, shortcuts); if (shortcut != null) { shortcuts.Add(shortcut); if (KnownShortcuts.ContainsKey(prop) == false) { KnownShortcuts.Add(prop, shortcut); } else { KnownShortcuts[prop] = shortcut; } } } if (actionProp != null) { foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (prop.IsActionArgProperty()) { RegisterShortcuts(prop.PropertyType, shortcuts); } } } }
/// <summary> /// Parses the given arguments using a command line arguments definition. Then, invokes the action /// that was specified. /// </summary> /// <param name="definition">The definition that defines a set of command line arguments and actions.</param> /// <param name="args"></param> /// <returns>The raw result of the parse with metadata about the specified action. The action is executed before returning.</returns> public static ArgAction InvokeAction(CommandLineArgumentsDefinition definition, params string[] args) { ArgAction ret = Execute(() => { return REPL.DriveREPL<ArgAction>(definition.Hooks.Where(h => h is TabCompletion).Select(h => h as TabCompletion).SingleOrDefault(), (a) => { var result = ParseAction(definition, a); if (result.HandledException == null) { result.Context.RunBeforeInvoke(); result.Invoke(); result.Context.RunAfterInvoke(); } return result; } , args); }); return ret; }
/// <summary> /// Creates a new instance of T and populates it's properties based on the given arguments. T must correctly /// implement the heuristics for Actions (or sub commands) because this method will not only detect the action /// specified on the command line, but will also find and execute the method that implements the action. /// </summary> /// <typeparam name="T">The argument scaffold type that must properly implement at least one action.</typeparam> /// <param name="args">The command line arguments to parse</param> /// <returns>The raw result of the parse with metadata about the specified action. The action is executed before returning.</returns> public static ArgAction<T> InvokeAction<T>(params string[] args) { ArgAction<T> ret = Execute<ArgAction<T>>(() => { return REPL.DriveREPL<ArgAction<T>>(typeof(T).Attr<TabCompletion>(), (a) => { var result = ParseAction<T>(a); if (result.HandledException == null) { result.Context.RunBeforeInvoke(); result.Invoke(); result.Context.RunAfterInvoke(); } return result; } , args); }); return ret; }
/// <summary> /// Parses the args for the given scaffold type and then calls the Main() method defined by the type. /// </summary> /// <param name="t">The argument scaffold type.</param> /// <param name="args">The command line arguments to parse</param> /// <returns>The raw result of the parse with metadata about the specified action.</returns> public static ArgAction InvokeMain(Type t, params string[] args) { ArgAction ret = Execute(() => { return REPL.DriveREPL<ArgAction>(t.Attr<TabCompletion>(), (a) => { var result = ParseAction(t, a); if (result.HandledException == null) { result.Context.RunBeforeInvoke(); result.Value.InvokeMainMethod(); result.Context.RunAfterInvoke(); } return result; } , args); }); return ret; }
private static T CreateEmptyResult <T>(ArgHook.HookContext context, ArgException ex = null, bool cancelled = false) { ArgAction ret = new ArgAction(); if (typeof(T) == typeof(ArgAction)) { ret = new ArgAction(); } else if (typeof(T).IsSubclassOf(typeof(ArgAction))) { ret = Activator.CreateInstance(typeof(T)) as ArgAction; } else { return(default(T)); } ret.HandledException = ex; ret.Definition = context.Definition; ret.Context = context; ret.Cancelled = cancelled; return((T)((object)ret)); }
private void ValidateArgScaffold(Type t, List <string> shortcuts = null, Type parentType = null) { if (parentType != null) { if (parentType.HasAttr <ArgIgnoreCase>() ^ t.HasAttr <ArgIgnoreCase>()) { throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base type then you must also specify it on each action type."); } else if (parentType.HasAttr <ArgIgnoreCase>() && parentType.Attr <ArgIgnoreCase>().IgnoreCase != t.Attr <ArgIgnoreCase>().IgnoreCase) { throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base and acton types then they must be configured to use the same value for IgnoreCase."); } } if (t.Attrs <ArgIgnoreCase>().Count > 1) { throw new InvalidArgDefinitionException("An attribute that is or derives from " + typeof(ArgIgnoreCase).Name + " was specified on your type more than once"); } var actionProp = ArgAction.GetActionProperty(t); shortcuts = shortcuts ?? new List <string>(); bool ignoreCase = true; if (t.HasAttr <ArgIgnoreCase>() && t.Attr <ArgIgnoreCase>().IgnoreCase == false) { ignoreCase = false; } foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (prop.Attr <ArgIgnoreAttribute>() != null) { continue; } if (prop.IsActionArgProperty() && actionProp != null) { continue; } if (ArgRevivers.CanRevive(prop.PropertyType) == false) { throw new InvalidArgDefinitionException("There is no reviver for type " + prop.PropertyType.Name + ". Offending Property: " + prop.DeclaringType.Name + "." + prop.GetArgumentName()); } var shortcut = ArgShortcut.GetShortcut(prop); if (ignoreCase && shortcut != null) { shortcut = shortcut.ToLower(); } if (shortcut != null && shortcuts.Contains(shortcut)) { throw new InvalidArgDefinitionException("Duplicate arg options with shortcut '" + ArgShortcut.GetShortcut(prop) + "'. Keep in mind that shortcuts are not case sensitive unless you use the [ArgIgnoreCase(false)] attribute. For example, Without this attribute the shortcuts '-a' and '-A' would cause this exception."); } else if (shortcut != null) { shortcuts.Add(shortcut); } } if (actionProp != null) { foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (prop.IsActionArgProperty()) { ArgAction.ResolveMethod(t, prop); ValidateArgScaffold(prop.PropertyType, shortcuts.ToArray().ToList(), t); } } } }
/// <summary> /// Generates color styled usage documentation for the given argument scaffold type. /// </summary> /// <typeparam name="T">Your custom argument scaffold type</typeparam> /// <param name="exeName">The name of your program or null if you want PowerArgs to automatically detect it.</param> /// <param name="options">Specify custom usage options</param> /// <returns></returns> public static ConsoleString GetStyledUsage <T>(string exeName = null, ArgUsageOptions options = null) { options = options ?? new ArgUsageOptions(); if (exeName == null) { var assembly = Assembly.GetEntryAssembly(); if (assembly == null) { throw new ArgException("PowerArgs could not determine the name of your executable automatically. This may happen if you run GetUsage<T>() from within unit tests. Use GetUsageT>(string exeName) in unit tests to avoid this exception."); } exeName = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); } ConsoleString ret = new ConsoleString(); ret += new ConsoleString("Usage: " + exeName, ConsoleColor.Cyan); var actionProperty = ArgAction.GetActionProperty <T>(); if (actionProperty != null) { ret.AppendUsingCurrentFormat(" <action> options\n\n"); foreach (var example in typeof(T).Attrs <ArgExample>()) { ret += new ConsoleString("EXAMPLE: " + example.Example + "\n" + example.Description + "\n\n", ConsoleColor.DarkGreen); } var global = GetOptionsUsage(typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public), true, options); if (string.IsNullOrEmpty(global.ToString()) == false) { ret += new ConsoleString("Global options:\n\n", ConsoleColor.Cyan) + global + "\n"; } ret += "Actions:"; foreach (PropertyInfo prop in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (prop.IsActionArgProperty() == false) { continue; } var actionDescription = prop.HasAttr <ArgDescription>() ? " - " + prop.Attr <ArgDescription>().Description : ""; ret += "\n\n" + prop.GetArgumentName().Substring(0, prop.GetArgumentName().Length - Constants.ActionArgConventionSuffix.Length) + actionDescription + "\n\n"; foreach (var example in prop.Attrs <ArgExample>()) { ret += new ConsoleString() + " EXAMPLE: " + new ConsoleString(example.Example + "\n", ConsoleColor.Green) + new ConsoleString(" " + example.Description + "\n\n", ConsoleColor.DarkGreen); } ret += GetOptionsUsage(prop.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public), false, options); } } else { ret.AppendUsingCurrentFormat(" options\n\n"); ret += GetOptionsUsage(typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public), false, options); ret += "\n"; foreach (var example in typeof(T).Attrs <ArgExample>()) { ret += new ConsoleString() + " EXAMPLE: " + new ConsoleString(example.Example + "\n", ConsoleColor.Green) + new ConsoleString(" " + example.Description + "\n\n", ConsoleColor.DarkGreen); } } return(ret); }
/// <summary> /// Given an action property, finds the method that implements the action. /// </summary> /// <param name="actionProperty">The property to resolve</param> /// <returns></returns> public static MethodInfo ResolveMethod(PropertyInfo actionProperty) { return(ArgAction.ResolveMethod(typeof(T), actionProperty)); }
private ArgAction ParseInternal(CommandLineArgumentsDefinition definition, string[] input) { // TODO - Validation should be consistently done against the definition, not against the raw type if (definition.ArgumentScaffoldType != null) { ValidateArgScaffold(definition.ArgumentScaffoldType); } var context = ArgHook.HookContext.Current; context.Definition = definition; _ambientDefinition = definition; definition.Validate(context); if (definition.ArgumentScaffoldType != null) { context.Args = Activator.CreateInstance(definition.ArgumentScaffoldType); } context.CmdLineArgs = input; context.RunBeforeParse(); context.ParserData = ArgParser.Parse(definition, context.CmdLineArgs); var actionToken = context.CmdLineArgs.FirstOrDefault(); var actionQuery = context.Definition.Actions.Where(a => a.IsMatch(actionToken)); if (actionQuery.Count() == 1) { context.SpecifiedAction = actionQuery.First(); } else if (actionQuery.Count() > 1) { throw new InvalidArgDefinitionException("There are multiple actions that match argument '" + actionToken + "'"); } context.RunBeforePopulateProperties(); CommandLineArgument.PopulateArguments(context.Definition.Arguments, context); context.Definition.SetPropertyValues(context.Args); object actionArgs = null; object[] actionParameters = null; if (context.SpecifiedAction == null && context.Definition.Actions.Count > 0) { if (context.CmdLineArgs.FirstOrDefault() == null) { throw new MissingArgException("No action was specified"); } else { throw new UnknownActionArgException(string.Format("Unknown action: '{0}'", context.CmdLineArgs.FirstOrDefault())); } } else if (context.SpecifiedAction != null) { PropertyInfo actionProp = null; if (context.Definition.ArgumentScaffoldType != null) { actionProp = ArgAction.GetActionProperty(context.Definition.ArgumentScaffoldType); } if (actionProp != null) { actionProp.SetValue(context.Args, context.SpecifiedAction.Aliases.First(), null); } context.ParserData.ImplicitParameters.Remove(0); CommandLineArgument.PopulateArguments(context.SpecifiedAction.Arguments, context); } context.RunAfterPopulateProperties(); if (context.SpecifiedAction != null) { actionArgs = context.SpecifiedAction.PopulateArguments(context.Args, ref actionParameters); } if (context.Definition.Metadata.HasMeta <AllowUnexpectedArgs>() == false) { if (context.ParserData.ImplicitParameters.Count > 0) { throw new UnexpectedArgException("Unexpected unnamed argument: " + context.ParserData.ImplicitParameters.First().Value); } if (context.ParserData.ExplicitParameters.Count > 0) { throw new UnexpectedArgException("Unexpected named argument: " + context.ParserData.ExplicitParameters.First().Key); } } else { definition.UnexpectedExplicitArguments = context.ParserData.ExplicitParameters; definition.UnexpectedImplicitArguments = context.ParserData.ImplicitParameters; } if (definition.ArgumentScaffoldType != null) { if (AmbientArgs.ContainsKey(definition.ArgumentScaffoldType)) { AmbientArgs[definition.ArgumentScaffoldType] = context.Args; } else { AmbientArgs.Add(definition.ArgumentScaffoldType, context.Args); } } PropertyInfo actionArgsPropertyInfo = null; if (context.SpecifiedAction != null) { if (context.SpecifiedAction.Source is PropertyInfo) { actionArgsPropertyInfo = context.SpecifiedAction.Source as PropertyInfo; } else if (context.SpecifiedAction.Source is MethodInfo) { actionArgsPropertyInfo = new ArgActionMethodVirtualProperty(context.SpecifiedAction.Source as MethodInfo); } } return(new ArgAction() { Value = context.Args, ActionArgs = actionArgs, ActionParameters = actionParameters, ActionArgsProperty = actionArgsPropertyInfo, ActionArgsMethod = context.SpecifiedAction != null ? context.SpecifiedAction.ActionMethod : null, Definition = context.Definition, Context = context, }); }
private void ValidateArgScaffold(Type t, List <string> shortcuts = null, Type parentType = null) { /* * Today, this validates the following: * * - IgnoreCase can't be different on parent and child scaffolds. * - No collisions on shortcut values for properties and enum values * - No reviver for type * */ if (parentType != null) { if (parentType.HasAttr <ArgIgnoreCase>() ^ t.HasAttr <ArgIgnoreCase>()) { throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base type then you must also specify it on each action type."); } else if (parentType.HasAttr <ArgIgnoreCase>() && parentType.Attr <ArgIgnoreCase>().IgnoreCase != t.Attr <ArgIgnoreCase>().IgnoreCase) { throw new InvalidArgDefinitionException("If you specify the " + typeof(ArgIgnoreCase).Name + " attribute on your base and acton types then they must be configured to use the same value for IgnoreCase."); } } if (t.Attrs <ArgIgnoreCase>().Count > 1) { throw new InvalidArgDefinitionException("An attribute that is or derives from " + typeof(ArgIgnoreCase).Name + " was specified on your type more than once"); } var actionProp = ArgAction.GetActionProperty(t); shortcuts = shortcuts ?? new List <string>(); bool ignoreCase = true; if (t.HasAttr <ArgIgnoreCase>() && t.Attr <ArgIgnoreCase>().IgnoreCase == false) { ignoreCase = false; } foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (prop.Attr <ArgIgnoreAttribute>() != null) { continue; } if (CommandLineAction.IsActionImplementation(prop)) { continue; } // This check happens in the CommandLineArgumentsDefinition validation method and should not be repeated here. Leaving the code commented while this bakes, but this code // should be removable in the future. //if (ArgRevivers.CanRevive(prop.PropertyType) == false) //{ // throw new InvalidArgDefinitionException("There is no reviver for type " + prop.PropertyType.Name + ". Offending Property: " + prop.DeclaringType.Name + "." + prop.Name); //} if (prop.PropertyType.IsEnum) { prop.PropertyType.ValidateNoDuplicateEnumShortcuts(ignoreCase); } var attrs = prop.Attrs <ArgShortcut>(); var noShortcutsAllowed = attrs.Where(a => a.Policy == ArgShortcutPolicy.NoShortcut).Count() != 0; var shortcutsOnly = attrs.Where(a => a.Policy == ArgShortcutPolicy.ShortcutsOnly).Count() != 0; var actualShortcutValues = attrs.Where(a => a.Policy == ArgShortcutPolicy.Default && a.Shortcut != null).Count() != 0; if (noShortcutsAllowed && shortcutsOnly) { throw new InvalidArgDefinitionException("You cannot specify a policy of NoShortcut and another policy of ShortcutsOnly."); } if (noShortcutsAllowed && actualShortcutValues) { throw new InvalidArgDefinitionException("You cannot specify a policy of NoShortcut and then also specify shortcut values via another attribute."); } if (shortcutsOnly && actualShortcutValues == false) { throw new InvalidArgDefinitionException("You specified a policy of ShortcutsOnly, but did not specify any shortcuts by adding another ArgShortcut attrivute."); } } if (actionProp != null) { foreach (PropertyInfo prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (CommandLineAction.IsActionImplementation(prop)) { ArgAction.ResolveMethod(t, prop); ValidateArgScaffold(prop.PropertyType, shortcuts.ToArray().ToList(), t); } } } foreach (var actionMethod in t.GetActionMethods()) { if (actionMethod.GetParameters().Length == 0) { continue; } ValidateArgScaffold(actionMethod.GetParameters()[0].ParameterType, shortcuts.ToArray().ToList(), t); } }
internal static bool IsActionImplementation(PropertyInfo property) { return(property.Name.EndsWith(Constants.ActionArgConventionSuffix) && property.HasAttr <ArgIgnoreAttribute>() == false && ArgAction.GetActionProperty(property.DeclaringType) != null); }