void AddPostOperation(IDebuggingHandler handler, OpenApiPathItem item, OpenApiOperation operation) { if (handler.GetType().ImplementsOpenGeneric(typeof(ICanHandlePostRequests <>))) { item.AddOperation(OperationType.Post, operation); } }
void ThrowIfNoHandleMethodsWasFound(IEnumerable <MethodInfo> handleMethods, IDebuggingHandler handler, Type handlerInterface, Type artifactType) { if (!handleMethods.Any()) { throw new NoAppropriateHandleMethodFound(handler, handlerInterface, artifactType); } }
OpenApiOperation GenerateOperation(IDebuggingHandler handler, Type artifact, SchemaRepository repository) { return(new OpenApiOperation { RequestBody = artifact.GetProperties().Length != 0 ? new OpenApiRequestBody { Required = true, Content = GenerateContentType("application/json", artifact, repository) } : null, Responses = GenerateResponses(handler, repository) }); }
async Task InvokeDebuggingHandler(HttpContext context, IDebuggingHandler handler, Type artifactType) { try { var artifact = await _deserializer.DeserializeArtifact(context.Request, artifactType).ConfigureAwait(false); await _invoker.InvokeDebugginHandlerMethod(context, handler, artifactType, artifact).ConfigureAwait(false); } catch (Exception exception) { await context.RespondWithException(exception).ConfigureAwait(false); } }
OpenApiResponses GenerateResponses(IDebuggingHandler handler, SchemaRepository repository) { var responses = new OpenApiResponses(); foreach ((var statusCode, var description) in handler.Responses) { responses.Add($"{statusCode}", new OpenApiResponse { Description = description, Content = GenerateContentType("text/plain", typeof(string), repository), }); } return(responses); }
/// <inheritdoc/> public MethodInfo FindMethod(IDebuggingHandler handler, Type handlerInterface, Type artifactType) { var handlerInterfaceTypeInfo = handlerInterface.GetTypeInfo(); var implementedGenericInterfaces = handler.GetType().GetInterfaces().Where(_ => _.IsGenericType); var matchingInterfaces = implementedGenericInterfaces.Where(_ => _.GetGenericTypeDefinition().GetTypeInfo() == handlerInterfaceTypeInfo); var suitableInterfaces = matchingInterfaces.Where(_ => _.GenericTypeArguments.Length == 1 && _.GenericTypeArguments[0].IsAssignableFrom(artifactType)); var interfaceMethods = suitableInterfaces.SelectMany(_ => _.GetMethods()); var handleMethods = interfaceMethods.Where(_ => _.Name.StartsWith("Handle", StringComparison.InvariantCultureIgnoreCase)); ThrowIfNoHandleMethodsWasFound(handleMethods, handler, handlerInterface, artifactType); ThrowIfMoreThanOneHandleMethodsWasFound(handleMethods, handler, handlerInterface, artifactType); return(handleMethods.First()); }
/// <inheritdoc/> public void ModifyDocument(IDebuggingHandler handler, OpenApiDocument document) { if (handler is DebuggingHandler) { var schemaGenerator = _schemaGeneratorFactory(); var repository = new SchemaRepository(); repository.PopulateWithDocumentSchemas(document); foreach ((_, var item) in document.Paths) { item.Parameters.Add(GenerateEventSourceIdParameter(schemaGenerator, repository)); } document.Components.Schemas = repository.Schemas; } }
/// <inheritdoc/> public async Task InvokeDebugginHandlerMethod(HttpContext context, IDebuggingHandler handler, Type artifactType, object artifact) { if (HttpMethods.IsGet(context.Request.Method) && handler.GetType().ImplementsOpenGeneric(typeof(ICanHandleGetRequests <>))) { var method = _methodFinder.FindMethod(handler, typeof(ICanHandleGetRequests <>), artifactType); await InvokeHandlerMethod(context, method, handler, artifact).ConfigureAwait(false); return; } if (HttpMethods.IsPost(context.Request.Method) && handler.GetType().ImplementsOpenGeneric(typeof(ICanHandlePostRequests <>))) { var method = _methodFinder.FindMethod(handler, typeof(ICanHandlePostRequests <>), artifactType); await InvokeHandlerMethod(context, method, handler, artifact).ConfigureAwait(false); return; } }
void GeneratePaths(OpenApiPaths paths, IDebuggingHandler handler, SchemaRepository repository) { foreach ((var path, var artifact) in handler.Artifacts) { var item = new OpenApiPathItem(); AddGetOperation(handler, item, GenerateOperation(handler, artifact, repository)); AddPostOperation(handler, item, GenerateOperation(handler, artifact, repository)); var tag = path.ToString().Contains('/', StringComparison.InvariantCultureIgnoreCase) ? path.ToString().Split('/')[1] : path.ToString(); foreach ((_, var operation) in item.Operations) { operation.Tags = new[] { new OpenApiTag { Name = tag } }; } paths.Add(path, item); } }
/// <inheritdoc/> public OpenApiDocument GenerateFor(IDebuggingHandler handler) { var repository = new SchemaRepository(); var paths = new OpenApiPaths(); GeneratePaths(paths, handler, repository); return(new OpenApiDocument { Info = new OpenApiInfo { Title = handler.Title, }, Paths = paths, Components = new OpenApiComponents { Schemas = repository.Schemas, }, }); }
/// <inheritdoc/> public void ModifyDocument(IDebuggingHandler handler, OpenApiDocument document) { var schemaGenerator = _schemaGeneratorFactory(); var repository = new SchemaRepository(); repository.PopulateWithDocumentSchemas(document); foreach ((_, var item) in document.Paths) { foreach ((_, var operation) in item.Operations) { if (operation.Parameters == null) { operation.Parameters = new List <OpenApiParameter>(); } operation.Parameters.Add(GenerateTenantIdParameter(schemaGenerator, repository)); } } document.Components.Schemas = repository.Schemas; }
async Task InvokeHandlerMethod(HttpContext context, MethodInfo method, IDebuggingHandler handler, object artifact) { try { var task = method.Invoke(handler, new[] { context, artifact }) as Task; await task.ConfigureAwait(false); } catch (TargetException exception) { throw new CouldNotInvokeHandleMethod(method, handler, artifact.GetType(), exception); } catch (TargetParameterCountException exception) { throw new CouldNotInvokeHandleMethod(method, handler, artifact.GetType(), exception); } catch (ArgumentException exception) { throw new CouldNotInvokeHandleMethod(method, handler, artifact.GetType(), exception); } }
void ThrowIfMoreThanOneHandleMethodsWasFound(IEnumerable <MethodInfo> handleMethods, IDebuggingHandler handler, Type handlerInterface, Type artifactType) { if (handleMethods.Count() > 1) { throw new MoreThanOneAppropriateHandleMethodFound(handler, handlerInterface, artifactType); } }
/// <summary> /// Initializes a new instance of the <see cref="NoAppropriateHandleMethodFound"/> class. /// </summary> /// <param name="handler">The <see cref="IDebuggingHandler"/> that was examined.</param> /// <param name="handlerInterface">The <see cref="Type"/> of the handler interface that was used.</param> /// <param name="artifactType">The <see cref="Type"/> of the artifact that should be handled.</param> public NoAppropriateHandleMethodFound(IDebuggingHandler handler, Type handlerInterface, Type artifactType) : base($"No appropriate Handle... method was found for {handler.GetType()} using the {handlerInterface} interface for artifacts of type {artifactType}.") { }
/// <summary> /// Initializes a new instance of the <see cref="CouldNotInvokeHandleMethod"/> class. /// </summary> /// <param name="method">The <see cref="MethodInfo"/> of the method that was invoked.</param> /// <param name="handler">The <see cref="IDebuggingHandler"/> that the method was invoked on.</param> /// <param name="artifactType">The <see cref="Type"/> of the artifact that was used to call the method.</param> /// <param name="exception">The actual <see cref="Exception"/> that was thrown.</param> public CouldNotInvokeHandleMethod(MethodInfo method, IDebuggingHandler handler, Type artifactType, Exception exception) : base($"Could not invoke method {method} on handler {handler} with artifact of type {artifactType}", exception) { }