private static void BuildOptionParameter( ReplBuilder builder, ReplCommandBuilder commandBuilder, ParameterInfo parameter, ReplOptionAttribute replOption, ReplCommandOptionParameterBuilder paramBuilder) { if (replOption.TypeName == null) { throw new ArgumentNullException(nameof(replOption.TypeName)); } paramBuilder .WithTypeName(replOption.TypeName) .WithCaption(replOption.Caption) .WithValueCount(replOption.ValueCount) .WithDescription(replOption.Caption); if (!parameter.HasDefaultValue) { paramBuilder.WithIsRequired(); } if (parameter.ParameterType.IsGenericType && parameter.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable <string>).GetGenericTypeDefinition()) { paramBuilder.WithIsRepeated(); } foreach (var replExample in parameter.GetCustomAttributes <ReplExampleAttribute>()) { paramBuilder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); if (replExample.Scope >= ReplExampleScope.Parent) { commandBuilder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); } if (replExample.Scope >= ReplExampleScope.All) { builder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); } } }
public ReplBuilder WithCommand(string name, Action <ReplCommandBuilder> configCommand) { var commandBuilder = new ReplCommandBuilder().WithName(name); configCommand.Invoke(commandBuilder); commands.Add(commandBuilder); return(this); }
public ReplCommandRuntime(ReplCommandBuilder builder) { this.Names = new ReadOnlyCollection <string>(builder.Names.ToArray()); this.Category = builder.Category; this.Caption = builder.Caption; this.Description = builder.description; // TODO: Check parameter ambiguities, only last positional can be repeated, required must be in order: true, true, false, false this.Parameters = new ReadOnlyCollection <ReplParameterRuntime>(builder.Parameters.Select(e => new ReplParameterRuntime(e)).ToArray()); this.Examples = new ReadOnlyCollection <ReplExampleRuntime>(builder.examples.Select(e => new ReplExampleRuntime(e)).ToArray()); this.PositionalParameters = new ReadOnlyCollection <ReplParameterRuntime>(this.Parameters.Where(p => p.ParameterType == ReplParameterType.Positional).ToArray()); if (builder.Execute == null) { throw new ArgumentNullException(nameof(builder.Execute)); } this.Execute = builder.Execute; }
private static void BuildFlagParameter( ReplBuilder builder, ReplCommandBuilder commandBuilder, ParameterInfo parameter, ReplFlagAttribute replFlag, ReplCommandFlagParameterBuilder paramBuilder) { if (parameter.ParameterType != typeof(bool)) { ConsoleEx.WriteLine(ConsoleColor.Red, $"Flag `{commandBuilder.Names.First()} {AsOptionName(parameter.Name)}` cannot have a type other than `bool`, but found with type `{parameter.ParameterType.Name}`"); } paramBuilder .WithCaption(replFlag.Caption) .WithDescription(replFlag.Caption); foreach (var replExample in parameter.GetCustomAttributes <ReplExampleAttribute>()) { paramBuilder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); if (replExample.Scope >= ReplExampleScope.Parent) { commandBuilder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); } if (replExample.Scope >= ReplExampleScope.All) { builder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); } } }
private static void BuildCommand( IServiceProvider serviceProvider, IReplBase replInstance, ReplBuilder builder, MethodInfo method, ReplCommandAttribute command, ReplCommandBuilder commandBuilder) { commandBuilder .WithCaption(command.Caption) .WithDescription(command.Description); foreach (var namesAttr in method.GetCustomAttributes <ReplNamesAttribute>()) { foreach (var name in namesAttr.Names) { commandBuilder.WithName(name); } } foreach (var replExample in method.GetCustomAttributes <ReplExampleAttribute>()) { commandBuilder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); if (replExample.Scope >= ReplExampleScope.Parent) { builder.WithExample(replExample.Command, exampleBuilder => { exampleBuilder .WithCaption(exampleBuilder.caption) .WithDescription(exampleBuilder.description); }); } } var parameters = method.GetParameters(); foreach (var parameter in parameters) { var replParam = parameter.GetCustomAttribute <ReplParamAttribute>(); var replOption = parameter.GetCustomAttribute <ReplOptionAttribute>(); var replFlag = parameter.GetCustomAttribute <ReplFlagAttribute>(); var fromServiceProvider = parameter.GetCustomAttribute <ReplServiceAttribute>() != null; if (replParam != null) { commandBuilder.WithPositional(parameter.Name, paramBuilder => { BuildPositionalParameter(builder, commandBuilder, parameter, replParam, paramBuilder); }); } else if (replOption != null) { commandBuilder.WithOption(parameter.Name, paramBuilder => { BuildOptionParameter(builder, commandBuilder, parameter, replOption, paramBuilder); }); } else if (replFlag != null) { commandBuilder.WithFlag(parameter.Name, paramBuilder => { BuildFlagParameter(builder, commandBuilder, parameter, replFlag, paramBuilder); }); } else { if (!parameter.HasDefaultValue && !fromServiceProvider && parameter.ParameterType != typeof(CancellationToken) && parameter.ParameterType != typeof(Dictionary <string, object>)) { string message = $"Parameter {parameter.Name} from command {method.Name} cannot be fulfilled"; ConsoleEx.WriteLine(ConsoleColor.Red, message); throw new InvalidOperationException(message); } } } Task ExecuteAsync(Dictionary <string, object> values, CancellationToken cancellationToken) { var paramValues = new object[parameters.Length]; // TODO: Optimize for (int i = 0; i < parameters.Length; i++) { if (values.TryGetValue(parameters[i].Name, out var value)) { // TODO: Bind depending on the param type paramValues[i] = value; } else if (parameters[i].GetCustomAttribute <ReplServiceAttribute>() != null) { if (parameters[i].HasDefaultValue) { paramValues[i] = serviceProvider.GetService(parameters[i].ParameterType); } else { paramValues[i] = serviceProvider.GetRequiredService(parameters[i].ParameterType); } } else if (parameters[i].ParameterType == typeof(CancellationToken)) { paramValues[i] = cancellationToken; } else if (parameters[i].ParameterType == typeof(Dictionary <string, object>)) { paramValues[i] = values; } else if (parameters[i].HasDefaultValue) { paramValues[i] = parameters[i].DefaultValue; } else { string message = $"Parameter {parameters[i].Name} from command {method.Name} cannot be bound"; ConsoleEx.WriteLine(ConsoleColor.Red, message); throw new InvalidOperationException(message); } } var result = method.Invoke(replInstance, paramValues); // TODO: Catch exceptions here or in the engine? if (result is Task task && typeof(Task).IsAssignableFrom(method.ReturnType)) { return(task); } return(Task.CompletedTask); } commandBuilder.WithExecute(ExecuteAsync); }