protected object ConvertToDelegate(object o, Type toType) { var toMethodInfo = toType.GetMethod("Invoke"); var toMethodParams = toMethodInfo.GetParameters(); var toMethodParamCount = toMethodParams.Length; MethodInfo fromMethod; object fromObject; FindMethod(o, toMethodParamCount, out fromObject, out fromMethod); // simplest case - when parameters are contravariant and result is covariant var toDelegate = Delegate.CreateDelegate(toType, fromObject, fromMethod, false); if (toDelegate != null) { return(toDelegate); } // use adapter with run-time types conversion var adapter = new DelegateAdapter(fromObject, fromMethod); foreach (var adapterMethod in adapter.GetType().GetMethods()) { if (adapterMethod.Name == "Invoke" && adapterMethod.GetParameters().Length == toMethodParamCount) { var resType = toMethodInfo.ReturnType != typeof(void) ? toMethodInfo.ReturnType : typeof(object); var genericTypes = new Type[toMethodParamCount + 1]; for (int i = 0; i < toMethodParams.Length; i++) { genericTypes[i] = toMethodParams[i].ParameterType; } genericTypes[toMethodParamCount] = resType; // last type for result var typedInvokeMethod = adapterMethod.MakeGenericMethod(genericTypes); LogManager.GetLogger(typeof(DelegateConverter)).Write(LogEvent.Info, typedInvokeMethod.ToString()); return(Delegate.CreateDelegate(toType, adapter, typedInvokeMethod, true)); } } throw new InvalidCastException(); }