/// <summary> /// Registers command handler. /// </summary> /// <remarks> /// <see cref="CommandAttribute.Formatter"/> must be defined. /// </remarks> /// <param name="handler">The command handler.</param> /// <typeparam name="TCommand">The type of the command supported by the handler.</typeparam> /// <returns>This builder.</returns> /// <exception cref="ArgumentNullException"><paramref name="handler"/> is <see langword="null"/>.</exception> /// <exception cref="GenericArgumentException">Type <typaparamref name="TCommand"/> is not annotated with <see cref="CommandAttribute"/> attribute or <see cref="CommandAttribute.Formatter"/> refers to the invalid formatter.</exception> public Builder Add <TCommand>(Func <TCommand, CancellationToken, ValueTask> handler) where TCommand : struct { if (handler is null) { throw new ArgumentNullException(nameof(handler)); } var attr = typeof(TCommand).GetCustomAttribute <CommandAttribute>(); if (attr is null || attr.Formatter is null) { throw new GenericArgumentException <TCommand>(ExceptionMessages.MissingCommandAttribute <TCommand>()); } var formatter = new FormatterInfo(attr); if (formatter.IsEmpty) { throw new GenericArgumentException <TCommand>(ExceptionMessages.MissingCommandFormatter <TCommand>()); } formatters.Add(typeof(TCommand), formatter); var interp = Activator.CreateInstance(typeof(CommandHandler <>).MakeGenericType(typeof(TCommand)), formatter, handler); interpreters.Add(attr.Id, Cast <CommandHandler>(interp)); return(this); }
public Parser(List<Token> tokens) { this.fi = new FormatterInfo(); this.tokens = tokens; this.tokenIndex = 0; this.indentLevel = 0; this.comments = new List<String>(); this.ignoreTypes = new List<TokenType>(){ TokenType.Comment, TokenType.Empty, }; }
/// <summary> /// Registers command handler. /// </summary> /// <remarks> /// <see cref="CommandAttribute.Formatter"/> is ignored by this method. /// </remarks> /// <param name="handler">The command handler.</param> /// <param name="formatter">Serializer/deserializer of the command type.</param> /// <typeparam name="TCommand">The type of the command supported by the handler.</typeparam> /// <returns>This builder.</returns> /// <exception cref="ArgumentNullException"><paramref name="handler"/> or <paramref name="formatter"/> is <see langword="null"/>.</exception> /// <exception cref="GenericArgumentException">Type <typaparamref name="TCommand"/> is not annotated with <see cref="CommandAttribute"/> attribute.</exception> public Builder Add <TCommand>(Func <TCommand, CancellationToken, ValueTask> handler, IFormatter <TCommand> formatter) where TCommand : struct { if (handler is null) { throw new ArgumentNullException(nameof(handler)); } if (formatter is null) { throw new ArgumentNullException(nameof(formatter)); } var id = typeof(TCommand).GetCustomAttribute <CommandAttribute>()?.Id ?? throw new GenericArgumentException <TCommand>(ExceptionMessages.MissingCommandAttribute <TCommand>()); interpreters.Add(id, new CommandHandler <TCommand>(formatter, handler)); formatters.Add(typeof(TCommand), FormatterInfo.Create(formatter, id)); return(this); }
/// <summary> /// Initializes a new interpreter and discovers methods marked /// with <see cref="CommandHandlerAttribute"/> attribute. /// </summary> protected CommandInterpreter() { var interpreters = new Dictionary <int, CommandHandler>(); var formatters = new Dictionary <Type, FormatterInfo>(); const BindingFlags publicInstanceMethod = BindingFlags.Public | BindingFlags.Instance; foreach (var method in GetType().GetMethods(publicInstanceMethod)) { var handlerAttr = method.GetCustomAttribute <CommandHandlerAttribute>(); if (handlerAttr is not null && method.ReturnType == typeof(ValueTask)) { var parameters = method.GetParameterTypes(); if (GetLength(parameters) != 2 || !parameters[0].IsValueType || parameters[1] != typeof(CancellationToken)) { continue; } var commandType = parameters[0]; var commandAttr = commandType.GetCustomAttribute <CommandAttribute>(); if (commandAttr is null || commandAttr.Formatter is null) { continue; } var formatter = new FormatterInfo(commandAttr); if (formatter.IsEmpty) { continue; } var interpreter = Delegate.CreateDelegate(typeof(Func <, ,>).MakeGenericType(commandType, typeof(CancellationToken), typeof(ValueTask)), method.IsStatic ? null : this, method); interpreters.Add(commandAttr.Id, Cast <CommandHandler>(Activator.CreateInstance(typeof(CommandHandler <>).MakeGenericType(commandType), formatter, interpreter))); formatters.Add(commandType, formatter); } } this.interpreters = CreateRegistry(interpreters); interpreters.Clear(); formatters.TrimExcess(); this.formatters = formatters; }
public static List<Token> LexerFile(FormatterInfo fi) { return LexerLines(IO.ReadFile(fi.Path, fi.Enc), fi.Path); }
public Parser(List<Token> tokens, FormatterInfo fi) : this(tokens) { this.fi = fi; this.tokens = tokens; }