public void TestGetIndexOfMatchingShim() { StubHelperTests stubHelperTests = new StubHelperTests(); Action staticAction = new Action(() => { }); Action <StubHelperTests> instanceAction = new Action <StubHelperTests>((@this) => { }); Shim shim = Shim.Replace(() => Console.Clear()).With(staticAction); Shim shim1 = Shim.Replace(() => Is.A <StubHelperTests>().TestGetIndexOfMatchingShim()).With(instanceAction); Shim shim2 = Shim.Replace(() => stubHelperTests.TestGetIndexOfMatchingShim()).With(instanceAction); PoseContext.Isolate(() => { }, shim, shim1, shim2); MethodInfo consoleMethodInfo = typeof(Console).GetMethod("Clear"); MethodInfo stubMethodInfo = typeof(StubHelperTests).GetMethod("TestGetIndexOfMatchingShim"); Assert.AreEqual(0, StubHelper.GetIndexOfMatchingShim(consoleMethodInfo, null)); Assert.AreEqual(1, StubHelper.GetIndexOfMatchingShim(stubMethodInfo, new StubHelperTests())); Assert.AreEqual(2, StubHelper.GetIndexOfMatchingShim(stubMethodInfo, stubHelperTests)); }
public static DynamicMethod GenerateStubForMethod(MethodInfo methodInfo) { ParameterInfo[] parameters = methodInfo.GetParameters(); List <Type> signatureParamTypes = new List <Type>(); List <Type> parameterTypes = new List <Type>(); if (!methodInfo.IsStatic) { if (methodInfo.IsForValueType()) { signatureParamTypes.Add(methodInfo.DeclaringType.MakeByRefType()); } else { signatureParamTypes.Add(methodInfo.DeclaringType); } } signatureParamTypes.AddRange(parameters.Select(p => p.ParameterType)); parameterTypes.AddRange(signatureParamTypes); parameterTypes.Add(typeof(RuntimeMethodHandle)); parameterTypes.Add(typeof(RuntimeTypeHandle)); DynamicMethod stub = new DynamicMethod( string.Format("stub_{0}_{1}", methodInfo.DeclaringType, methodInfo.Name), methodInfo.ReturnType, parameterTypes.ToArray(), StubHelper.GetOwningModule(), true); ILGenerator ilGenerator = stub.GetILGenerator(); ilGenerator.DeclareLocal(typeof(MethodInfo)); ilGenerator.DeclareLocal(typeof(int)); ilGenerator.DeclareLocal(typeof(IntPtr)); Label rewriteLabel = ilGenerator.DefineLabel(); Label returnLabel = ilGenerator.DefineLabel(); ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 2); ilGenerator.Emit(OpCodes.Ldarg, parameterTypes.Count - 1); ilGenerator.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetMethodFromHandle", new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) })); ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo)); ilGenerator.Emit(OpCodes.Stloc_0); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(methodInfo.IsStatic || methodInfo.IsForValueType() ? OpCodes.Ldnull : OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetIndexOfMatchingShim", new Type[] { typeof(MethodBase), typeof(Object) })); ilGenerator.Emit(OpCodes.Stloc_1); ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Ldc_I4_M1); ilGenerator.Emit(OpCodes.Ceq); ilGenerator.Emit(OpCodes.Brtrue_S, rewriteLabel); var methodBase = StubHelper.GetShimReplacementMethod(StubHelper.GetIndexOfMatchingShim(methodInfo as MethodBase, null)); if (StubHelper.MethodBaseIsShimmyDynamic(methodBase)) { var dynamicMethod = StubHelper.GetDynamicMethodFromDynamicMethodBase(methodBase); EmitArguments(ilGenerator, signatureParamTypes); ilGenerator.EmitCall(OpCodes.Call, dynamicMethod, null); } else { // do things the classic Pose way ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetShimReplacementMethod")); ilGenerator.Emit(OpCodes.Stloc_0); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer")); ilGenerator.Emit(OpCodes.Stloc_2); ilGenerator.Emit(OpCodes.Ldloc_1); ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetShimDelegateTarget")); EmitArguments(ilGenerator, signatureParamTypes); ilGenerator.Emit(OpCodes.Ldloc_2); ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.HasThis, methodInfo.ReturnType, signatureParamTypes.ToArray(), null); } ilGenerator.Emit(OpCodes.Br_S, returnLabel); ilGenerator.MarkLabel(rewriteLabel); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("CreateRewriter", new Type[] { typeof(MethodBase) })); ilGenerator.Emit(OpCodes.Call, typeof(MethodRewriter).GetMethod("Rewrite")); ilGenerator.Emit(OpCodes.Castclass, typeof(MethodInfo)); ilGenerator.Emit(OpCodes.Stloc_0); for (int i = 0; i < signatureParamTypes.Count; i++) { ilGenerator.Emit(OpCodes.Ldarg, i); } ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Call, typeof(StubHelper).GetMethod("GetMethodPointer")); ilGenerator.EmitCalli(OpCodes.Calli, CallingConventions.Standard, methodInfo.ReturnType, signatureParamTypes.ToArray(), null); ilGenerator.MarkLabel(returnLabel); ilGenerator.Emit(OpCodes.Ret); return(stub); }