/// <inheritdoc /> public void Handle(IControllerBindingContext context, Action next) { next(); foreach (var parameter in context.Parameters.Where(p => !p.HasBinding && p.Info.ParameterType.IsClass)) { parameter.SetBinding(messageContext => messageContext.Config.DependencyResolver.Resolve(parameter.Info.ParameterType)); } }
public void Handle(IControllerBindingContext context, Action next) { if (context.Method.GetCustomAttribute <StartAttribute>() != null) { return; } RegisterYieldPointResult(context); RegisterContinuationFilter(context); next(); ValidateRequestResponse(context); }
private static void ValidateRequestResponse(IControllerBindingContext context) { var request = context.MessageClass?.GetCustomAttribute <RequestAttribute>(); if (request?.Response == null) { return; } if (!context.Result.Info.ParameterType.IsTypeOrTaskOf(t => t == request.Response || t == typeof(IYieldPoint), out _)) { throw new ResponseExpectedException($"Response of class {request.Response.FullName} expected in controller {context.Method.DeclaringType?.FullName}, method {context.Method.Name}"); } }
/// <inheritdoc /> public void Handle(IControllerBindingContext context, Action next) { next(); if (context.Result.HasHandler) { return; } var hasClassResult = context.Result.Info.ParameterType.IsTypeOrTaskOf(t => t.IsClass, out var isTaskOf, out var actualType); var request = context.MessageClass?.GetCustomAttribute <RequestAttribute>(); var expectedClassResult = request?.Response; // Verify the return type matches with the Request attribute of the message class. This is a backwards incompatible change in // Tapeti 1.2: if you just want to publish another message as a result of the incoming message, explicitly call IPublisher.Publish. // ReSharper disable once ConvertIfStatementToSwitchStatement if (!hasClassResult && expectedClassResult != null || hasClassResult && expectedClassResult != actualType) { throw new ArgumentException($"Message handler must return type {expectedClassResult?.FullName ?? "void"} in controller {context.Method.DeclaringType?.FullName}, method {context.Method.Name}, found: {actualType?.FullName ?? "void"}"); } if (!hasClassResult) { return; } if (isTaskOf) { var handler = GetType().GetMethod("PublishGenericTaskResult", BindingFlags.NonPublic | BindingFlags.Static)?.MakeGenericMethod(actualType); Debug.Assert(handler != null, nameof(handler) + " != null"); context.Result.SetHandler(async(messageContext, value) => { await(Task) handler.Invoke(null, new[] { messageContext, value }); }); } else { context.Result.SetHandler((messageContext, value) => Reply(value, messageContext)); } }
/// <inheritdoc /> public void Handle(IControllerBindingContext context, Action next) { if (!context.HasMessageClass) { if (context.Parameters.Count == 0) { throw new TopologyConfigurationException($"First parameter of method {context.Method.Name} in controller {context.Method.DeclaringType?.Name} must be a message class"); } var parameter = context.Parameters[0]; if (!parameter.Info.ParameterType.IsClass) { throw new TopologyConfigurationException($"First parameter {parameter.Info.Name} of method {context.Method.Name} in controller {context.Method.DeclaringType?.Name} must be a message class"); } parameter.SetBinding(messageContext => messageContext.Message); context.SetMessageClass(parameter.Info.ParameterType); } next(); }
private static void RegisterYieldPointResult(IControllerBindingContext context) { if (!context.Result.Info.ParameterType.IsTypeOrTaskOf(typeof(IYieldPoint), out var isTaskOf)) { return; } if (isTaskOf) { context.Result.SetHandler(async(messageContext, value) => { var yieldPoint = await(Task <IYieldPoint>) value; if (yieldPoint != null) { await HandleYieldPoint(messageContext, yieldPoint); } }); } else { context.Result.SetHandler((messageContext, value) => HandleYieldPoint(messageContext, (IYieldPoint)value)); } }
private static void RegisterContinuationFilter(IControllerBindingContext context) { var continuationAttribute = context.Method.GetCustomAttribute <ContinuationAttribute>(); if (continuationAttribute == null) { return; } context.SetBindingTargetMode(BindingTargetMode.Direct); context.Use(new FlowContinuationMiddleware()); if (context.Result.HasHandler) { return; } // Continuation without IYieldPoint indicates a ParallelRequestBuilder response handler, // make sure to store it's state as well if (context.Result.Info.ParameterType == typeof(Task)) { context.Result.SetHandler(async(messageContext, value) => { await(Task) value; await HandleParallelResponse(messageContext); }); } else if (context.Result.Info.ParameterType == typeof(void)) { context.Result.SetHandler((messageContext, value) => HandleParallelResponse(messageContext)); } else { throw new ArgumentException($"Result type must be IYieldPoint, Task or void in controller {context. Method.DeclaringType?.FullName}, method {context.Method.Name}"); } }
/// <inheritdoc /> public void ApplyBindingMiddleware(IControllerBindingContext context, Action lastHandler) { MiddlewareHelper.Go(bindingMiddleware, (handler, next) => handler.Handle(context, next), lastHandler); }