using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Moq; using Moq.Language; using Moq.Language.Flow; public static class MoqExtensions { private const BindingFlags privateInstanceFlags = BindingFlags.Instance | BindingFlags.NonPublic; public static ICallbackResult OutCallback(this ICallback mock, Delegate callback) { RefCallbackHelper.SetCallback(mock, callback); return (ICallbackResult)mock; } public static ICallbackResult RefCallback(this ICallback mock, Delegate callback) { RefCallbackHelper.SetCallback(mock, callback); return (ICallbackResult)mock; } public static IReturnsThrows OutCallback(this ICallback mock, Delegate callback) where TMock : class { RefCallbackHelper.SetCallback(mock, callback); return (IReturnsThrows)mock; } public static IReturnsThrows RefCallback(this ICallback mock, Delegate callback) where TMock : class { RefCallbackHelper.SetCallback(mock, callback); return (IReturnsThrows)mock; } private static class RefCallbackHelper { private static readonly Action setCallbackWithoutArgumentsAction = CreateSetCallbackWithoutArgumentsAction(); public static void SetCallback(object mock, Delegate callback) { setCallbackWithoutArgumentsAction(mock, callback); } private static Action CreateSetCallbackWithoutArgumentsAction() { ParameterExpression mockParameter = Expression.Parameter(typeof(object)); ParameterExpression actionParameter = Expression.Parameter(typeof(Delegate)); Type type = typeof(Mock<>).Assembly.GetType("Moq.MethodCall", true); MethodInfo method = type.GetMethod("SetCallbackWithArguments", privateInstanceFlags); if (method == null) throw new InvalidOperationException(); return Expression.Lambda>( Expression.Call(Expression.Convert(mockParameter, type), method, actionParameter), mockParameter, actionParameter).Compile(); } } }