protected MethodBuilder GetWrapperMethodFromEmitter( MethodBase executingTestMethod, Type[] publicParameterTypes, Type publicReturnType, MethodInfo innerMethod) { var methodName = executingTestMethod.DeclaringType.Name + "_" + executingTestMethod.Name; var methodBuilder = _typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, publicReturnType, publicParameterTypes); var ilGenerator = methodBuilder.GetILGenerator(); var emitter = new MethodWrapperEmitter(ilGenerator, innerMethod, publicParameterTypes, publicReturnType); emitter.EmitStaticMethodBody(); return(methodBuilder); }
/// <summary> /// Creates a <see cref="Delegate"/> that can be used to invoke the method identified by the <paramref name="methodInfo"/>. /// </summary> /// <param name="methodInfo">The method to wrap.</param> /// <param name="delegateType"> /// The <see cref="Delegate"/> type. The signature must always include the instance-parameter as first parameter even if the /// <paramref name="methodInfo"/> refers to a static method. /// </param> /// <returns> /// An instance of the <paramref name="delegateType"/> that can be used to invoke the method identified by the <paramref name="methodInfo"/>. /// </returns> public static Delegate CreateMethodCallerDelegate(MethodInfo methodInfo, Type delegateType) { ArgumentUtility.CheckNotNull("methodInfo", methodInfo); ArgumentUtility.CheckNotNullAndTypeIsAssignableFrom("delegateType", delegateType, typeof(Delegate)); var delegateMethod = delegateType.GetMethod("Invoke"); Assertion.IsNotNull(delegateMethod); var name = methodInfo.DeclaringType + "_" + methodInfo.Name + "_" + Guid.NewGuid(); var returnType = delegateMethod.ReturnType; var parameterTypes = delegateMethod.GetParameters().Select(p => p.ParameterType).ToArray(); DynamicMethod dynamicMethod; if (methodInfo.DeclaringType.IsInterface) { // Using the owner-less version for non-nested interfaces helps circumvent issues in the CLR regarding the combination of // DynamicMethods and domain-neutrally loaded assemblies. This case could happen if the interface is from mscorlib, e.g. ICollection. // See http://support.microsoft.com/kb/971030/en-us for details. if (methodInfo.DeclaringType.IsNested) { dynamicMethod = new DynamicMethod(name, returnType, parameterTypes, methodInfo.DeclaringType.DeclaringType, false); } else { dynamicMethod = new DynamicMethod(name, returnType, parameterTypes, false); } } else { dynamicMethod = new DynamicMethod(name, returnType, parameterTypes, methodInfo.DeclaringType, false); } var ilGenerator = dynamicMethod.GetILGenerator(); var emitter = new MethodWrapperEmitter(ilGenerator, methodInfo, parameterTypes, returnType); emitter.EmitStaticMethodBody(); return(dynamicMethod.CreateDelegate(delegateType)); }
public void EmitMethodBody_ForPrivatePropertyGetter_ForReferenceType() { Type declaringType = typeof(ClassWithReferenceTypeProperties); var propertyInfo = declaringType.GetProperty("PropertyWithPrivateGetterAndSetter", BindingFlags.NonPublic | BindingFlags.Instance); var methodInfo = propertyInfo.GetGetMethod(true); Type returnType = typeof(object); Type[] parameterTypes = new[] { typeof(object) }; var dynamicMethod = new DynamicMethod("", returnType, parameterTypes, declaringType, false); var ilGenerator = dynamicMethod.GetILGenerator(); var emitter = new MethodWrapperEmitter(ilGenerator, methodInfo, parameterTypes, returnType); emitter.EmitStaticMethodBody(); var propertyGetter = (Func <object, object>)dynamicMethod.CreateDelegate(typeof(Func <object, object>)); var expectedValue = new SimpleReferenceType(); var obj = new ClassWithReferenceTypeProperties(); obj.SetPropertyWithPrivateGetterAndSetter(expectedValue); Assert.That(propertyGetter(obj), Is.SameAs(expectedValue)); }