/// <summary> /// Adds middleware specified by its type to the list of delegates that will be applied to the schema when invoking <see cref="IFieldMiddlewareBuilder.ApplyTo(ISchema)"/>. /// <br/><br/> /// Middleware will be created using the DI container obtained from the <see cref="Schema"/>. /// </summary> /// <param name="builder">Interface for connecting middlewares to a schema.</param> /// <param name="middleware">Middleware type.</param> /// <returns>Reference to the same <see cref="IFieldMiddlewareBuilder"/>.</returns> public static IFieldMiddlewareBuilder Use(this IFieldMiddlewareBuilder builder, System.Type middleware) { if (!typeof(IFieldMiddleware).IsAssignableFrom(middleware)) { throw new ArgumentException($"Field middleware of type '{middleware.FullName}' must implement the {nameof(IFieldMiddleware)} interface", nameof(middleware)); } return(builder.Use((schema, next) => { if (schema == null) { throw new InvalidOperationException("Schema is null. Schema required for resolving middlewares from DI container."); } // Not an ideal solution, but at least it allows to work with custom schemas which are not inherited from Schema type if (!(schema is IServiceProvider provider)) { throw new NotSupportedException($"'{schema.GetType().FullName}' should implement 'IServiceProvider' interface for resolving middlewares."); } var instance = (IFieldMiddleware)provider.GetService(middleware); if (instance == null) { throw new InvalidOperationException($"Field middleware of type '{middleware.FullName}' must be registered in the DI container."); } return context => instance.Resolve(context, next); })); }
public static IFieldMiddlewareBuilder Use(this IFieldMiddlewareBuilder builder, System.Type middleware) { return(builder.Use(next => { var methods = middleware.GetMethods(BindingFlags.Instance | BindingFlags.Public); var invokeMethods = methods.Where(m => string.Equals(m.Name, InvokeMethodName, StringComparison.Ordinal)).ToArray(); if (invokeMethods.Length > 1) { throw new InvalidOperationException($"There should be only a single method named {InvokeMethodName}. Middleware actually has {invokeMethods.Length} methods."); } if (invokeMethods.Length == 0) { throw new InvalidOperationException($"Could not find a method named {InvokeMethodName}. Middleware must have a public instance method named {InvokeMethodName}."); } var methodInfo = invokeMethods[0]; if (!typeof(Task <object>).IsAssignableFrom(methodInfo.ReturnType)) { throw new InvalidOperationException($"The {InvokeMethodName} method should return a Task<object>."); } var parameters = methodInfo.GetParameters(); if (parameters.Length != 2 || parameters[0].ParameterType != typeof(ResolveFieldContext) || parameters[1].ParameterType != typeof(FieldMiddlewareDelegate)) { throw new InvalidOperationException($"The {InvokeMethodName} method of middleware should take a parameter of type {nameof(ResolveFieldContext)} as the first parameter and a parameter of type {nameof(FieldMiddlewareDelegate)} as the second parameter."); } var instance = Activator.CreateInstance(middleware); return context => (Task <object>)methodInfo.Invoke(instance, new object[] { context, next }); })); }
/// <summary> /// Applies all delegates specified by the middleware builder to the schema. /// <br/><br/> /// When applying to the schema, modifies the resolver of each field of each graph type adding required behavior. /// Therefore, as a rule, this method should be called only once - during schema initialization. /// </summary> public void ApplyMiddleware(IFieldMiddlewareBuilder fieldMiddlewareBuilder) { var transform = (fieldMiddlewareBuilder ?? throw new ArgumentNullException(nameof(fieldMiddlewareBuilder))).Build(); // allocation free optimization if no middlewares are defined if (transform != null) { ApplyMiddleware(transform); } }
/// <summary> /// Adds middleware specified by its type to the list of delegates that will be applied to the schema when invoking <see cref="IFieldMiddlewareBuilder.ApplyTo(ISchema)"/>. /// <br/><br/> /// Middleware will be created using the DI container obtained from the <see cref="Schema"/>. /// </summary> /// <typeparam name="T">Middleware type.</typeparam> /// <param name="builder">Interface for connecting middlewares to a schema.</param> /// <returns>Reference to the same <see cref="IFieldMiddlewareBuilder"/>.</returns> public static IFieldMiddlewareBuilder Use <T>(this IFieldMiddlewareBuilder builder) where T : IFieldMiddleware => Use(builder, typeof(T));
/// <summary> /// Adds the specified delegate to the list of delegates that will be applied to the schema when invoking <see cref="IFieldMiddlewareBuilder.ApplyTo(ISchema)"/>. /// <br/><br/> /// This is a compatibility shim when compiling delegates without schema specified. /// </summary> /// <param name="builder">Interface for connecting middlewares to a schema.</param> /// <param name="middleware">Middleware delegate.</param> /// <returns>Reference to the same <see cref="IFieldMiddlewareBuilder"/>.</returns> public static IFieldMiddlewareBuilder Use(this IFieldMiddlewareBuilder builder, Func <FieldMiddlewareDelegate, FieldMiddlewareDelegate> middleware) => builder.Use((_, next) => middleware(next));
/// <summary> /// Adds middleware to the list of delegates that will be applied to the schema when invoking <see cref="IFieldMiddlewareBuilder.ApplyTo(ISchema)"/>. /// </summary> /// <param name="builder">Interface for connecting middlewares to a schema.</param> /// <param name="middleware">Middleware instance.</param> /// <returns>Reference to the same <see cref="IFieldMiddlewareBuilder"/>.</returns> public static IFieldMiddlewareBuilder Use(this IFieldMiddlewareBuilder builder, IFieldMiddleware middleware) => builder.Use(next => context => middleware.Resolve(context, next));
public static IFieldMiddlewareBuilder Use <T>(this IFieldMiddlewareBuilder builder) { return(Use(builder, typeof(T))); }
/// <summary> /// Adds middleware specified by its type to the list of delegates that will be applied to the schema when invoking <see cref="ApplyTo(ISchema)"/>. /// <br/><br/> /// Middleware will be created using the DI container obtained from the <see cref="Schema"/>. /// </summary> /// <param name="builder">Interface for connecting middlewares to a schema.</param> /// <param name="middleware">Middleware type.</param> /// <returns>Reference to the same <see cref="IFieldMiddlewareBuilder"/>.</returns> public static IFieldMiddlewareBuilder Use(this IFieldMiddlewareBuilder builder, System.Type middleware) {