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 }); }
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 !); }
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); }
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)); }
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)); }
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)); }
private Task <object> Invoke(SubscribedMethod method, object[] parameters, bool executeAsync) => executeAsync ? InvokeAsync(method, parameters) : Task.FromResult(InvokeSync(method, parameters));
private object[] GetShiftedParameterValuesArray(SubscribedMethod method) => new object[1].Concat( _argumentsResolver.GetAdditionalParameterValues(method)) .ToArray();
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)); }
private static object UnwrapEnvelopeIfNeeded(object message, SubscribedMethod subscribedMethod) => !typeof(IEnvelope).IsAssignableFrom(subscribedMethod.MessageType) && message is IEnvelope envelope &&