private IAsyncEnumerator <object> GetStreamingEnumerator(HubConnectionContext connection, string invocationId, ObjectMethodExecutor methodExecutor, object result, Type resultType) { if (result != null) { var observableInterface = IsIObservable(resultType) ? resultType : resultType.GetInterfaces().FirstOrDefault(IsIObservable); if (observableInterface != null) { return(AsyncEnumeratorAdapters.FromObservable(result, observableInterface, CreateCancellation())); } if (IsChannel(resultType, out var payloadType)) { return(AsyncEnumeratorAdapters.FromChannel(result, payloadType, CreateCancellation())); } } _logger.InvalidReturnValueFromStreamingMethod(methodExecutor.MethodInfo.Name); throw new InvalidOperationException($"The value returned by the streaming method '{methodExecutor.MethodInfo.Name}' is null, does not implement the IObservable<> interface or is not a ReadableChannel<>."); CancellationToken CreateCancellation() { var streamCts = new CancellationTokenSource(); connection.ActiveRequestCancellationSources.TryAdd(invocationId, streamCts); return(CancellationTokenSource.CreateLinkedTokenSource(connection.ConnectionAbortedToken, streamCts.Token).Token); } }
private bool IsStreamed(HubConnectionContext connection, ObjectMethodExecutor methodExecutor, object result, Type resultType, out IAsyncEnumerator <object> enumerator) { if (result == null) { enumerator = null; return(false); } // TODO: We need to support cancelling the stream without a client disconnect as well. var observableInterface = IsIObservable(resultType) ? resultType : resultType.GetInterfaces().FirstOrDefault(IsIObservable); if (observableInterface != null) { enumerator = AsyncEnumeratorAdapters.FromObservable(result, observableInterface, connection.ConnectionAbortedToken); return(true); } else if (IsChannel(resultType, out var payloadType)) { enumerator = AsyncEnumeratorAdapters.FromChannel(result, payloadType, connection.ConnectionAbortedToken); return(true); } else { // Not streamed enumerator = null; return(false); } }
private bool IsStreamed(HubConnectionContext connection, string invocationId, ObjectMethodExecutor methodExecutor, object result, Type resultType, out IAsyncEnumerator <object> enumerator) { if (result == null) { enumerator = null; return(false); } var observableInterface = IsIObservable(resultType) ? resultType : resultType.GetInterfaces().FirstOrDefault(IsIObservable); if (observableInterface != null) { enumerator = AsyncEnumeratorAdapters.FromObservable(result, observableInterface, CreateCancellation()); return(true); } else if (IsChannel(resultType, out var payloadType)) { enumerator = AsyncEnumeratorAdapters.FromChannel(result, payloadType, CreateCancellation()); return(true); } else { // Not streamed enumerator = null; return(false); } CancellationToken CreateCancellation() { var streamCts = new CancellationTokenSource(); connection.ActiveRequestCancellationSources.TryAdd(invocationId, streamCts); return(CancellationTokenSource.CreateLinkedTokenSource(connection.ConnectionAbortedToken, streamCts.Token).Token); } }