private void ConfigureMethod(MethodInfo method, ParameterInfo[] parameters) { var returnType = method.ReturnType; var isVoid = returnType == typeof(void); if (isVoid) { _dispatchType |= DispatchType.Void; LogicalReturnType = returnType; } else if (typeof(Promise).IsAssignableFrom(returnType)) { _dispatchType |= DispatchType.Promise; var promise = returnType.GetOpenTypeConformance(typeof(Promise <>)); LogicalReturnType = promise != null ? promise.GetGenericArguments()[0] : typeof(object); } else if (typeof(Task).IsAssignableFrom(returnType)) { _dispatchType |= DispatchType.Task; var task = returnType.GetOpenTypeConformance(typeof(Task <>)); LogicalReturnType = task != null ? task.GetGenericArguments()[0] : typeof(object); } else { LogicalReturnType = returnType; } if (!method.IsGenericMethodDefinition) { switch (parameters.Length) { #region Early Bound case 0: _delegate = isVoid ? (Delegate)RuntimeHelper.CreateCallNoArgs(method) : RuntimeHelper.CreateFuncNoArgs(method); _dispatchType |= DispatchType.FastNoArgs; return; case 1: _delegate = isVoid ? (Delegate)RuntimeHelper.CreateCallOneArg(method) : RuntimeHelper.CreateFuncOneArg(method); _dispatchType |= DispatchType.FastOneArg; return; case 2: _delegate = isVoid ? (Delegate)RuntimeHelper.CreateCallTwoArgs(method) : RuntimeHelper.CreateFuncTwoArgs(method); _dispatchType |= DispatchType.FastTwoArgs; return; case 3: _delegate = isVoid ? (Delegate)RuntimeHelper.CreateCallThreeArgs(method) : RuntimeHelper.CreateFuncThreeArgs(method); _dispatchType |= DispatchType.FastThreeArgs; return; case 4: _delegate = isVoid ? (Delegate)RuntimeHelper.CreateCallFourArgs(method) : RuntimeHelper.CreateFuncFourArgs(method); _dispatchType |= DispatchType.FastFourArgs; return; case 5: _delegate = isVoid ? (Delegate)RuntimeHelper.CreateCallFiveArgs(method) : RuntimeHelper.CreateFuncFiveArgs(method); _dispatchType |= DispatchType.FastFiveArgs; return; #endregion default: _dispatchType |= DispatchType.LateBound; return; } } var argSources = parameters .Where(p => p.ParameterType.ContainsGenericParameters) .Select(p => Tuple.Create(p.Position, p.ParameterType)) .ToList(); if (returnType.ContainsGenericParameters) { if (IsAsync) { returnType = returnType.GenericTypeArguments[0]; } argSources.Add(Tuple.Create(UseReturn, returnType)); } var methodArgs = method.GetGenericArguments(); var typeMapping = new Tuple <int, int> [methodArgs.Length]; foreach (var source in argSources) { var sourceArg = source.Item2; if (sourceArg.IsGenericParameter) { if (methodArgs.Length == 1 && methodArgs[0] == sourceArg) { typeMapping[0] = Tuple.Create(source.Item1, UseArgument); } continue; } var sourceGenericArgs = sourceArg.GetGenericArguments(); for (var i = 0; i < methodArgs.Length; ++i) { if (typeMapping[i] != null) { continue; } var index = Array.IndexOf(sourceGenericArgs, methodArgs[i]); if (index >= 0) { typeMapping[i] = Tuple.Create(source.Item1, index); } } if (!typeMapping.Contains(null)) { break; } } if (typeMapping.Contains(null)) { throw new InvalidOperationException( $"Type mapping for {method.GetDescription()} could not be inferred"); } _mapping = typeMapping; _dispatchType |= DispatchType.LateBound; _closed = new ConcurrentDictionary <MethodInfo, MethodDispatch>(); }