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));
        }