예제 #1
0
        /// <summary>
        /// Creates and caches a new, closed/invokable continue-with method out of ContinueWith&lt;T&gt; for each method called on the target.
        /// </summary>
        /// <param name="input">The input.</param>
        /// <returns>MethodInfo.</returns>
        MethodInfo GetContinueWith(
            IMethodInvocation input)
        {
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            if (!input.IsAsyncCall())
            {
                return(null);
            }

            var        returnType            = ((MethodInfo)input.MethodBase).ReturnType;
            var        handlerTypeReturnType = new HandlerTypeReturnType(GetType(), returnType);
            MethodInfo continueWith;

            // if we have it cached already - return it
            using (SyncMethodToContinueWith.ReaderLock())
                if (HandlerTypeReturnTypeToContinueWith.TryGetValue(handlerTypeReturnType, out continueWith))
                {
                    return(continueWith);
                }

            // get the continueWith MethodInfo
            MethodInfo genericContinueWith;

            using (SyncHandlerToGenericContinueWith.ReaderLock())
                genericContinueWith = HandlerToGenericContinueWith[GetType()];        // if it is not overridden, it will be null!

            continueWith = genericContinueWith?.MakeGenericMethod(returnType);

            using (SyncMethodToContinueWith.WriterLock())
                return(HandlerTypeReturnTypeToContinueWith[handlerTypeReturnType] = continueWith);
        }
예제 #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseCallHandler{T}"/> class.
        /// </summary>
        protected BaseCallHandler()
        {
            // Get the method info for an overridden ContinueWith<TResult>, if exists in the inheriting call handler:
            using (SyncHandlerToGenericContinueWith.UpgradableReaderLock())
                if (!HandlerToGenericContinueWith.TryGetValue(GetType(), out MethodInfo continueWithGeneric))
                {
                    continueWithGeneric = GetType().GetMethod(
                        nameof(ContinueWith),
                        BindingFlags.Instance | BindingFlags.NonPublic,
                        null,
                        new[] { typeof(IMethodInvocation), typeof(IMethodReturn), typeof(T) },
                        null);

                    var isOverridden = continueWithGeneric.IsOverridden() ||
                                       GetType().GetMethods().Any(mi => mi.Name == nameof(DoContinueWith) && mi.IsOverridden());

                    using (SyncHandlerToGenericContinueWith.WriterLock())
                        HandlerToGenericContinueWith[GetType()] = isOverridden ? continueWithGeneric : null;
                }
        }