Ejemplo n.º 1
0
        /// <summary>
        /// Gets what 'kind' of return the method provides.
        /// </summary>
        private static returnKindEnum GetReturnType(MethodInfo m)
        {
            returnKindEnum rt = 0;

            if (m.ReturnType == typeof(void))
            {
                rt = returnKindEnum.voidType;
            }
            else if (m.ReturnType == typeof(Task) &&
                     m.ReturnType.IsConstructedGenericType == false)
            {
                rt = returnKindEnum.TaskType;
            }
            else if (IsTaskReturnType(m.ReturnType))
            {
                if (IsAsyncEnumerableType(GetInnerReturnType(m.ReturnType)))
                {
                    rt = returnKindEnum.TaskAsyncEnumReturnType;
                }
                else if (IsChannelReaderType(GetInnerReturnType(m.ReturnType)))
                {
                    rt = returnKindEnum.TaskChannelReaderReturnType;
                }
                else
                {
                    rt = returnKindEnum.TaskReturnType;
                }
            }
            else if (IsAsyncEnumerableType(m.ReturnType))
            {
                rt = returnKindEnum.AsyncEnumReturnType;
            }
            else if (IsChannelReaderType(m.ReturnType))
            {
                rt = returnKindEnum.ChannelReaderReturnType;
            }
            else
            {
                rt = returnKindEnum.ReturnType;
            }

            return(rt);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Determines which method to call for the invocation
        /// </summary>
        /// <returns>The selected Method on the <see cref="HubConnection"/> to use.</returns>
        private static MethodInfo CreateHubMethod(bool useInvokeForAll, MethodInfo method, Type retType, returnKindEnum rett)
        {
            switch (rett)
            {
            case returnKindEnum.voidType:
            case returnKindEnum.TaskType:
                //Firing order:
                //      AlwaysInvoke? ->Invoke
                //      AlwaySend?  ->Send
                //      invokeForAll true->Invoke
                //                   false->Send
                return(((useInvokeForAll &&
                         method.GetCustomAttributes()
                         .Any(a => a is AlwaysSendAttribute) ==
                         false) || method.GetCustomAttributes()
                        .Any(a => a is AlwaysInvokeAttribute))
                        ? typeof(HubExtender).GetMethod(
                           nameof(HubExtender.PerformInvokeCoreAsyncNoReturn))
                        : typeof(HubExtender).GetMethod(
                           nameof(HubExtender.PerformSendCoreAsync)));

            case returnKindEnum.AsyncEnumReturnType:
                //If getting back an async enum, we need to stream.
                return(typeof(HubExtender)
                       .GetMethod(
                           nameof(HubExtender.PerformStreamCoreAsync))
                       ?.MakeGenericMethod(new[] { retType }));

            case returnKindEnum.TaskAsyncEnumReturnType:
                //Edge case: The API for once isn't returning a Task
                //So PerformStreamCoreAsyncTask wraps in a task for us.
                return(typeof(HubExtender)
                       .GetMethod(
                           nameof(HubExtender.PerformStreamCoreAsyncTask))
                       ?.MakeGenericMethod(new[] { retType }));

            case returnKindEnum.TaskChannelReaderReturnType:
            case returnKindEnum.ChannelReaderReturnType:
                //ChannelReader is given back as Task<ChannelReader<T>>
                //So we follow GetAwaiter().GetResult() semantics here.
                return(typeof(HubExtender)
                       .GetMethod(
                           nameof(HubExtender.PerformChannelReadStreamCoreAsync))
                       ?.MakeGenericMethod(new[] { retType }));

            case returnKindEnum.TaskReturnType:
            case returnKindEnum.ReturnType:
            default:
                //Logically speaking this is default regardless.
                return(typeof(HubExtender)
                       .GetMethod(
                           nameof(HubExtender.PerformInvokeCoreAsyncReturn))
                       ?.MakeGenericMethod(new[] { retType }));
            }
        }