private bool TryGetStreamingEnumerator(HubConnectionContext connection, string invocationId, ObjectMethodExecutor methodExecutor, object result, Type resultType, out IAsyncEnumerator <object> enumerator) { if (result != null) { // TODO: cache reflection for performance, on HubMethodDescriptor maybe? resultType = UnwrapTask(resultType); var observableInterface = IsIObservable(resultType) ? resultType : resultType.GetInterfaces().FirstOrDefault(IsIObservable); if (observableInterface != null) { enumerator = AsyncEnumeratorAdapters.FromObservable(result, observableInterface, CreateCancellation()); return(true); } if (IsChannel(resultType, out var payloadType)) { enumerator = AsyncEnumeratorAdapters.FromChannel(result, payloadType, CreateCancellation()); return(true); } } enumerator = null; return(false); CancellationToken CreateCancellation() { var streamCts = new CancellationTokenSource(); connection.ActiveRequestCancellationSources.TryAdd(invocationId, streamCts); return(CancellationTokenSource.CreateLinkedTokenSource(connection.ConnectionAbortedToken, streamCts.Token).Token); } }
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())); } } Log.InvalidReturnValueFromStreamingMethod(_logger, 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); } }