InvokeWithCollectionAsync(
            IReadOnlyCollection <object> messages,
            SubscribedMethod subscribedMethod,
            object?[] arguments,
            IEnumerableMessageArgumentResolver enumerableResolver,
            bool executeAsync)
        {
            if (messages.Count == 1 && messages.AsReadOnlyList()[0] is IMessageStreamProvider streamProvider &&
                streamProvider.AllowSubscribeAsEnumerable &&
                enumerableResolver is IStreamEnumerableMessageArgumentResolver resolverFromStreamProvider)
            {
                return(InvokeWithStreamEnumerable(
                           messages,
                           subscribedMethod,
                           arguments,
                           resolverFromStreamProvider));
            }

            messages = FilterMessagesAndUnwrapEnvelopes(messages, subscribedMethod).ToList();

            if (messages.Count == 0)
            {
                return(messages, null);
            }

            var target = subscribedMethod.ResolveTargetType(_serviceProvider);

            arguments[0] = enumerableResolver.GetValue(messages, subscribedMethod.MessageType);

            var returnValue = await InvokeAsync(target, subscribedMethod.MethodInfo, arguments, executeAsync)
                              .ConfigureAwait(false);

            return(messages, new[] { returnValue });
        }
Ejemplo n.º 2
0
        private static object InvokeWithStreamEnumerable(
            IMessageStreamProvider messageStreamProvider,
            SubscribedMethod subscribedMethod,
            object?[] arguments,
            IStreamEnumerableMessageArgumentResolver streamEnumerableResolver,
            IServiceProvider serviceProvider)
        {
            var target = subscribedMethod.ResolveTargetType(serviceProvider);

            var lazyStream = streamEnumerableResolver.GetValue(
                messageStreamProvider,
                subscribedMethod.MessageType,
                subscribedMethod.Filters);

            return(Task.Run(
                       async() =>
            {
                try
                {
                    await lazyStream.WaitUntilCreatedAsync().ConfigureAwait(false);

                    arguments[0] = lazyStream.Value;
                }
                catch (OperationCanceledException)
                {
                    return;
                }

                await subscribedMethod.MethodInfo.InvokeWithActivityWithoutBlockingAsync(
                    target,
                    arguments)
                .ConfigureAwait(false);
            }));
        }
        InvokeForEachMessageAsync(
            IReadOnlyCollection <object> messages,
            SubscribedMethod subscribedMethod,
            object?[] arguments,
            ISingleMessageArgumentResolver singleResolver,
            bool executeAsync)
        {
            messages = FilterMessagesAndUnwrapEnvelopes(messages, subscribedMethod).ToList();

            if (messages.Count == 0)
            {
                return(messages, null);
            }

            var target = subscribedMethod.ResolveTargetType(_serviceProvider);

            var returnValues = await messages
                               .SelectAsync(
                message =>
            {
                arguments[0] = singleResolver.GetValue(message);
                return(InvokeAsync(target, subscribedMethod.MethodInfo, arguments, executeAsync));
            })
                               .ConfigureAwait(false);

            return(messages, returnValues.ToList());
        }
 private static IEnumerable <object> FilterMessagesAndUnwrapEnvelopes(
     IEnumerable <object> messages,
     SubscribedMethod subscribedMethod)
 {
     foreach (var message in messages)
     {
         if (message is IEnvelope envelope && envelope.AutoUnwrap &&
             subscribedMethod.MessageType.IsInstanceOfType(envelope.Message))
         {
             yield return(envelope.Message !);
         }
Ejemplo n.º 5
0
        private Task <object> InvokeAsync(SubscribedMethod method, object[] parameters)
        {
            if (!method.Info.MethodInfo.ReturnsTask())
            {
                return(Task.Run(() => method.Info.MethodInfo.Invoke(method.Target, parameters)));
            }

            var result = method.Info.MethodInfo.Invoke(method.Target, parameters);

            return(((Task)result).GetReturnValue());
        }
        private object?[] GetArgumentValuesArray(SubscribedMethod method)
        {
            var values = new object?[method.Parameters.Count];

            for (int i = 1; i < method.Parameters.Count; i++)
            {
                var parameterType = method.Parameters[i].ParameterType;

                values[i] = method.AdditionalArgumentsResolvers[i - 1].GetValue(parameterType, _serviceProvider);
            }

            return(values);
        }
Ejemplo n.º 7
0
        private object InvokeSync(SubscribedMethod method, object[] parameters)
        {
            if (!method.Info.MethodInfo.ReturnsTask())
            {
                return(method.Info.MethodInfo.Invoke(method.Target, parameters));
            }

            return(AsyncHelper.RunSynchronously <object>(() =>
            {
                var result = (Task)method.Info.MethodInfo.Invoke(method.Target, parameters);
                return result.GetReturnValue();
            }));
        }
        public async Task <IEnumerable <object> > Invoke(SubscribedMethod method, IEnumerable <object> messages, bool executeAsync)
        {
            var(messageArgumentResolver, messageType) = _argumentsResolver.GetMessageArgumentResolver(method);

            if (messageArgumentResolver == null)
            {
                return(Enumerable.Empty <object>());
            }

            messages = messages.OfType(messageType);

            if (!messages.Any())
            {
                return(Enumerable.Empty <object>());
            }

            var target          = method.ResolveTargetType(_serviceProvider);
            var parameterValues = GetShiftedParameterValuesArray(method);

            IEnumerable <object> returnValues;

            switch (messageArgumentResolver)
            {
            case ISingleMessageArgumentResolver singleResolver:
                returnValues = (await messages
                                .OfType(messageType)
                                .SelectAsync(
                                    message =>
                {
                    parameterValues[0] = singleResolver.GetValue(message);
                    return(Invoke(target, method, parameterValues, executeAsync));
                },
                                    method.IsParallel,
                                    method.MaxDegreeOfParallelism))
                               .ToList();
                break;

            case IEnumerableMessageArgumentResolver enumerableResolver:
                parameterValues[0] = enumerableResolver.GetValue(messages, messageType);

                returnValues = new[] { await Invoke(target, method, parameterValues, executeAsync) };
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(await _returnValueHandler.HandleReturnValues(returnValues, executeAsync));
        }
Ejemplo n.º 9
0
        private static Task <object?> InvokeWithSingleMessageAsync(
            object message,
            SubscribedMethod subscribedMethod,
            object?[] arguments,
            ISingleMessageArgumentResolver singleResolver,
            IServiceProvider serviceProvider,
            bool executeAsync)
        {
            message = UnwrapEnvelopeIfNeeded(message, subscribedMethod);

            var target = subscribedMethod.ResolveTargetType(serviceProvider);

            arguments[0] = singleResolver.GetValue(message);
            return(subscribedMethod.MethodInfo.InvokeWithActivityAsync(target, arguments, executeAsync));
        }
Ejemplo n.º 10
0
        InvokeWithStreamEnumerable(
            IReadOnlyCollection <object> messages,
            SubscribedMethod subscribedMethod,
            object?[] arguments,
            IStreamEnumerableMessageArgumentResolver streamEnumerableResolver)
        {
            var streamProviders = FilterMessageStreamEnumerableMessages(messages, subscribedMethod).ToArray();

            if (streamProviders.Length == 0)
            {
                return(streamProviders, null);
            }

            var target = subscribedMethod.ResolveTargetType(_serviceProvider);

            var resultTasks = streamProviders
                              .Select(
                streamProvider =>
            {
                var lazyStream = streamEnumerableResolver.GetValue(
                    streamProvider,
                    subscribedMethod.MessageType);

                return(Task.Run(
                           async() =>
                {
                    try
                    {
                        await lazyStream.WaitUntilCreated().ConfigureAwait(false);

                        arguments[0] = lazyStream.Value;
                    }
                    catch (OperationCanceledException)
                    {
                        return;
                    }

                    await InvokeWithoutBlockingAsync(target, subscribedMethod.MethodInfo, arguments)
                    .ConfigureAwait(false);
                }));
            });

            return(messages, resultTasks.ToArray());
        }
        public async Task <MethodInvocationResult> InvokeAsync(
            SubscribedMethod subscribedMethod,
            IReadOnlyCollection <object> messages,
            bool executeAsync)
        {
            messages = ApplyFilters(subscribedMethod.Filters, messages);

            if (messages.Count == 0)
            {
                return(new MethodInvocationResult(messages));
            }

            var arguments = GetArgumentValuesArray(subscribedMethod);

            IReadOnlyCollection <object?>?returnValues;

            switch (subscribedMethod.MessageArgumentResolver)
            {
            case ISingleMessageArgumentResolver singleResolver:
                (messages, returnValues) = await InvokeForEachMessageAsync(
                    messages,
                    subscribedMethod,
                    arguments,
                    singleResolver,
                    executeAsync).ConfigureAwait(false);

                break;

            case IEnumerableMessageArgumentResolver enumerableResolver:
                (messages, returnValues) = await InvokeWithCollectionAsync(
                    messages,
                    subscribedMethod,
                    arguments,
                    enumerableResolver,
                    executeAsync).ConfigureAwait(false);

                break;

            case IStreamEnumerableMessageArgumentResolver streamEnumerableResolver:
                (messages, returnValues) = InvokeWithStreamEnumerable(
                    messages,
                    subscribedMethod,
                    arguments,
                    streamEnumerableResolver);

                break;

            default:
                throw new SubscribedMethodInvocationException(
                          $"The message argument resolver ({subscribedMethod.MessageArgumentResolver}) " +
                          "must implement either ISingleMessageArgumentResolver, IEnumerableMessageArgumentResolver " +
                          "or IStreamEnumerableMessageArgumentResolver.");
            }

            if (returnValues == null)
            {
                return(new MethodInvocationResult(messages));
            }

            var unhandledReturnValues =
                await _returnValueHandler.HandleReturnValuesAsync(returnValues, executeAsync)
                .ConfigureAwait(false);

            return(new MethodInvocationResult(messages, unhandledReturnValues));
        }
Ejemplo n.º 12
0
 private Task <object> Invoke(SubscribedMethod method, object[] parameters, bool executeAsync) =>
 executeAsync
         ? InvokeAsync(method, parameters)
         : Task.FromResult(InvokeSync(method, parameters));
Ejemplo n.º 13
0
 private object[] GetShiftedParameterValuesArray(SubscribedMethod method) =>
 new object[1].Concat(
     _argumentsResolver.GetAdditionalParameterValues(method))
 .ToArray();
Ejemplo n.º 14
0
        public static async Task <MethodInvocationResult> InvokeAsync(
            SubscribedMethod subscribedMethod,
            object message,
            IServiceProvider serviceProvider,
            bool executeAsync)
        {
            if (IsFiltered(subscribedMethod.Filters, message))
            {
                return(MethodInvocationResult.NotInvoked);
            }

            var arguments = GetArgumentValuesArray(subscribedMethod, serviceProvider);

            object?returnValue;

            switch (subscribedMethod.MessageArgumentResolver)
            {
            case ISingleMessageArgumentResolver singleResolver:
                returnValue = await InvokeWithSingleMessageAsync(
                    message,
                    subscribedMethod,
                    arguments,
                    singleResolver,
                    serviceProvider,
                    executeAsync).ConfigureAwait(false);

                break;

            case IStreamEnumerableMessageArgumentResolver streamEnumerableResolver:
                returnValue = InvokeWithStreamEnumerable(
                    (IMessageStreamProvider)message,
                    subscribedMethod,
                    arguments,
                    streamEnumerableResolver,
                    serviceProvider);

                break;

            default:
                throw new SubscribedMethodInvocationException(
                          $"The message argument resolver ({subscribedMethod.MessageArgumentResolver}) " +
                          "must implement either ISingleMessageArgumentResolver, IEnumerableMessageArgumentResolver " +
                          "or IStreamEnumerableMessageArgumentResolver.");
            }

            if (returnValue == null)
            {
                return(MethodInvocationResult.Invoked);
            }

            bool returnValueWasHandled =
                await serviceProvider
                .GetRequiredService <ReturnValueHandlerService>()
                .HandleReturnValuesAsync(returnValue, executeAsync)
                .ConfigureAwait(false);

            if (returnValueWasHandled)
            {
                return(MethodInvocationResult.Invoked);
            }

            return(MethodInvocationResult.WithReturnValue(returnValue));
        }
Ejemplo n.º 15
0
 private static object UnwrapEnvelopeIfNeeded(object message, SubscribedMethod subscribedMethod) =>
 !typeof(IEnvelope).IsAssignableFrom(subscribedMethod.MessageType) &&
 message is IEnvelope envelope &&