public DispatchResult Dispatch(object target, params object[] args) { if (TargetOrArgumentIsNull(target, args)) { return(new DispatchResult(DispatchStatus.NoMatch)); } MethodInvoker method = _dispatchTable.Match(args); if (method != null) { return(InvokeMethod(method, target, args)); } try { MethodInfo info = TryReflectionMatch(args); if (info.MethodHandle != _multiMethod.MethodHandle) // always use MethodInfo.MethodHandle to compare! { method = MethodInvokerHelper.CreateInvoker(info); } else { method = delegate { return(new DispatchResult(DispatchStatus.NoMatch)); }; } } catch (AmbiguousMatchException) { method = delegate { return(new DispatchResult(DispatchStatus.AmbiguousMatch)); }; } _dispatchTable.Add(args, method); DispatchResult result = InvokeMethod(method, target, args); result.IsDynamicInvoke = true; return(result); }
private Dispatcher(Type implementation, MethodInfo multiMethod, bool is32BitPlatform) { Constraints.CheckImplementationType(implementation); Constraints.CheckMultiMethod(multiMethod); int argumentCount = multiMethod.GetParameters().Length; DispatchTable dispatchTable = new DispatchTable(argumentCount, is32BitPlatform); Type currentType = implementation; while (currentType != typeof(object)) { MethodInfo[] methods = currentType.GetMethods( DefaultBindingFlags | BindingFlags.DeclaredOnly); foreach (MethodInfo candidate in methods) { if (candidate.MethodHandle != multiMethod.MethodHandle && candidate.Name == multiMethod.Name && candidate.GetParameters().Length == argumentCount && !candidate.ContainsGenericParameters && !HasInterfaceOrAbstractParameter(candidate)) { Type[] types = GetParameterTypes(candidate); //System.Diagnostics.Debug.WriteLine( // string.Format("{0}.{1}", candidate.DeclaringType, candidate)); dispatchTable.InternalAdd(types, MethodInvokerHelper.CreateInvoker(candidate)); } } currentType = currentType.BaseType; } _implementation = implementation; _multiMethod = multiMethod; _dispatchTable = dispatchTable; }