public static IDirectiveBuilder UseDirective(this IDirectiveBuilder builder, [DynamicallyAccessedMembers(DirectiveAccessibility)] Type directive, params object[] args) { var applicationServices = builder.ApplicationServices; return(builder.Use(next => { var methods = directive.GetMethods(BindingFlags.Instance | BindingFlags.Public); var invokeMethods = methods.Where(m => string.Equals(m.Name, InvokeMethodName, StringComparison.Ordinal) || string.Equals(m.Name, InvokeAsyncMethodName, StringComparison.Ordinal) ).ToArray(); if (invokeMethods.Length > 1) { throw new InvalidOperationException($"Multiple public '{InvokeMethodName}' or '{InvokeAsyncMethodName}' methods are available."); } if (invokeMethods.Length == 0) { throw new InvalidOperationException($"No public '{InvokeMethodName}' or '{InvokeAsyncMethodName}' method found for directive of type '{directive}'."); } var methodInfo = invokeMethods[0]; if (!typeof(Task).IsAssignableFrom(methodInfo.ReturnType)) { throw new InvalidOperationException($"'{InvokeMethodName}' or '{InvokeAsyncMethodName}' does not return an object of type '{nameof(Task)}'."); } var parameters = methodInfo.GetParameters(); if (parameters.Length == 0 || parameters[0].ParameterType != typeof(HtcHttpContext)) { throw new InvalidOperationException($"The '{InvokeMethodName}' or '{InvokeAsyncMethodName}' method's first argument must be of type '{nameof(HtcHttpContext)}'."); } var ctorArgs = new object[args.Length + 1]; ctorArgs[0] = next; Array.Copy(args, 0, ctorArgs, 1, args.Length); var instance = ActivatorUtilities.CreateInstance(builder.ApplicationServices, directive, ctorArgs); if (parameters.Length == 1) { return (DirectiveDelegate)methodInfo.CreateDelegate(typeof(DirectiveDelegate), instance); } var factory = Compile <object>(methodInfo, parameters); return context => { var serviceProvider = context.RequestServices ?? applicationServices; if (serviceProvider == null) { throw new InvalidOperationException($"'{nameof(IServiceProvider)}' is not available."); } return factory(instance, context, serviceProvider); }; })); }
public static IDirectiveBuilder UseDirective <[DynamicallyAccessedMembers(DirectiveAccessibility)] TDirective>(this IDirectiveBuilder builder, params object[] args) { return(builder.UseDirective(typeof(TDirective), args)); }