Ejemplo n.º 1
0
        /// <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));
            }
        }
Ejemplo n.º 2
0
        public void Handle(IControllerBindingContext context, Action next)
        {
            if (context.Method.GetCustomAttribute <StartAttribute>() != null)
            {
                return;
            }

            RegisterYieldPointResult(context);
            RegisterContinuationFilter(context);

            next();

            ValidateRequestResponse(context);
        }
Ejemplo n.º 3
0
        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}");
            }
        }
Ejemplo n.º 4
0
        /// <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));
            }
        }
Ejemplo n.º 5
0
        /// <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();
        }
Ejemplo n.º 6
0
        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));
            }
        }
Ejemplo n.º 7
0
        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}");
            }
        }
Ejemplo n.º 8
0
 /// <inheritdoc />
 public void ApplyBindingMiddleware(IControllerBindingContext context, Action lastHandler)
 {
     MiddlewareHelper.Go(bindingMiddleware,
                         (handler, next) => handler.Handle(context, next),
                         lastHandler);
 }