示例#1
0
        /// <summary>
        /// Emits a Console.WriteLine call using the current CilWorker.
        /// </summary>
        /// <param name="IL">The target CilWorker.</param>
        /// <param name="text">The text that will be written to the console.</param>
        public static void EmitWriteLine(this CilWorker IL, string text)
        {
            var body          = IL.GetBody();
            var method        = body.Method;
            var declaringType = method.DeclaringType;
            var module        = declaringType.Module;

            var writeLineMethod = typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null);

            IL.Emit(OpCodes.Ldstr, text);
            IL.Emit(OpCodes.Call, module.Import(writeLineMethod));
        }
示例#2
0
        /// <summary>
        /// Pushes the stack trace of the currently executing method onto the stack.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="module">The module that contains the host method.</param>
        public static void PushStackTrace(this CilWorker IL, ModuleDefinition module)
        {
            ConstructorInfo stackTraceConstructor =
                typeof(StackTrace).GetConstructor(new[] { typeof(int), typeof(bool) });
            MethodReference stackTraceCtor = module.Import(stackTraceConstructor);

            OpCode addDebugSymbols = OpCodes.Ldc_I4_0;

            IL.Emit(OpCodes.Ldc_I4_1);
            IL.Emit(addDebugSymbols);
            IL.Emit(OpCodes.Newobj, stackTraceCtor);
        }
示例#3
0
        /// <summary>
        /// Converts the return value of a method into the <paramref name="returnType">target type</paramref>.
        /// If the target type is void, then the value will simply be popped from the stack.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="module">The module that contains the host method.</param>
        /// <param name="returnType">The method return type itself.</param>
        public static void PackageReturnValue(this CilWorker IL, ModuleDefinition module, TypeReference returnType)
        {
            TypeReference voidType = module.ImportType(typeof(void));

            if (returnType == voidType)
            {
                IL.Emit(OpCodes.Pop);
                return;
            }

            IL.Emit(OpCodes.Unbox_Any, returnType);
        }
示例#4
0
        /// <summary>
        /// Pushes the current <paramref name="field"/> onto the stack.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="field">The field that represents the <see cref="FieldInfo"/> that will be pushed onto the stack.</param>
        /// <param name="module">The module that contains the target field.</param>
        public static void PushField(this CilWorker IL, FieldReference field, ModuleDefinition module)
        {
            var getFieldFromHandle = module.ImportMethod <FieldInfo>("GetFieldFromHandle",
                                                                     typeof(RuntimeFieldHandle),
                                                                     typeof(RuntimeTypeHandle));

            var declaringType = GetDeclaringType(field.DeclaringType);

            IL.Emit(OpCodes.Ldtoken, field);
            IL.Emit(OpCodes.Ldtoken, declaringType);
            IL.Emit(OpCodes.Call, getFieldFromHandle);
        }
示例#5
0
        /// <summary>
        /// Emits the instructions that obtain the <see cref="IAroundInvoke"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method        = IL.GetMethod();
            TypeDefinition   declaringType = method.DeclaringType;
            ModuleDefinition module        = declaringType.Module;

            MethodReference getSurroundingImplementation = module.Import(_getSurroundingImplementationMethod);

            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Call, getSurroundingImplementation);
            IL.Emit(OpCodes.Stloc, _surroundingClassImplementation);
        }
示例#6
0
        /// <summary>
        /// Causes the <see cref="CilWorker"/> to make the method throw a
        /// <see cref="NotImplementedException"/> if the method cannot be found.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> responsible for emitting the method body.</param>
        protected virtual void ImplementNotFound(CilWorker IL)
        {
            MethodBody       body          = IL.GetBody();
            TypeDefinition   declaringType = body.Method.DeclaringType;
            ModuleDefinition module        = declaringType.Module;

            // throw new NotImplementedException();
            MethodReference notImplementedConstructor = module.ImportConstructor <NotImplementedException>();

            IL.Emit(OpCodes.Newobj, notImplementedConstructor);
            IL.Emit(OpCodes.Throw);
        }
示例#7
0
        /// <summary>
        /// Adds a prolog to the given method body.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the given method body.</param>
        public void AddProlog(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();

            _surroundingImplementation      = method.AddLocal <IAroundInvoke>();
            _surroundingClassImplementation = method.AddLocal <IAroundInvoke>();

            Instruction      skipProlog     = IL.Create(OpCodes.Nop);
            TypeDefinition   declaringType  = method.DeclaringType;
            ModuleDefinition module         = declaringType.Module;
            TypeReference    modifiableType = module.ImportType <IModifiableType>();

            if (method.HasThis)
            {
                IL.Emit(OpCodes.Ldarg_0);
                IL.Emit(OpCodes.Isinst, modifiableType);
                IL.Emit(OpCodes.Brfalse, skipProlog);
            }

            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipProlog);

            // var provider = this.MethodReplacementProvider;

            if (_getMethodReplacementProvider != null)
            {
                _getMethodReplacementProvider.Emit(IL);
            }

            var getAroundInvokeProvider = new GetAroundInvokeProvider(_aroundInvokeProvider, _providerName);

            getAroundInvokeProvider.Emit(IL);

            // if (aroundInvokeProvider != null ) {
            Instruction skipGetSurroundingImplementation     = IL.Create(OpCodes.Nop);
            var         getSurroundingImplementationInstance = new GetSurroundingImplementationInstance(_aroundInvokeProvider,
                                                                                                        _invocationInfo,
                                                                                                        _surroundingImplementation,
                                                                                                        skipGetSurroundingImplementation);

            getSurroundingImplementationInstance.Emit(IL);

            // }

            IL.Append(skipGetSurroundingImplementation);
            var emitBeforeInvoke = new EmitBeforeInvoke(_invocationInfo, _surroundingClassImplementation,
                                                        _surroundingImplementation, _registryType);

            emitBeforeInvoke.Emit(IL);

            IL.Append(skipProlog);
        }
        private void EmitGetMethodReplacement(CilWorker IL, IMethodSignature hostMethod, VariableDefinition provider)
        {
            // var replacement = MethodReplacementProvider.GetReplacement(info);
            IL.Emit(OpCodes.Ldloc, provider);

            // Push the host instance
            var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, _getReplacement);
            IL.Emit(OpCodes.Stloc, _replacement);
        }
        /// <summary>
        /// Rewrites a target method using the given CilWorker.
        /// </summary>
        /// <param name="method">The target method.</param>
        /// <param name="IL">The CilWorker that will be used to rewrite the target method.</param>
        /// <param name="oldInstructions">The original instructions from the target method body.</param>
        public void Rewrite(MethodDefinition method, CilWorker IL,
                            IEnumerable <Instruction> oldInstructions)
        {
            MethodDefinition targetMethod = _parameters.TargetMethod;
            CilWorker        worker       = targetMethod.GetILGenerator();
            ModuleDefinition module       = worker.GetModule();


            _getInterceptionDisabled.Emit(worker);

            // Construct the InvocationInfo instance
            Instruction skipInvocationInfo = worker.Create(OpCodes.Nop);

            worker.Emit(OpCodes.Ldloc, _parameters.InterceptionDisabled);
            worker.Emit(OpCodes.Brtrue, skipInvocationInfo);

            MethodDefinition interceptedMethod = targetMethod;

            _emitter.Emit(targetMethod, interceptedMethod, _parameters.InvocationInfo);

            Instruction skipGetReplacementProvider = IL.Create(OpCodes.Nop);

            // var provider = this.MethodReplacementProvider;
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipGetReplacementProvider);

            _getInstanceMethodReplacementProvider.Emit(IL);
            _surroundMethodBody.AddProlog(worker);

            IL.Append(skipGetReplacementProvider);

            worker.Append(skipInvocationInfo);
            _getClassMethodReplacementProvider.Emit(worker);


            TypeReference returnType = targetMethod.ReturnType.ReturnType;

            _addMethodReplacement.Emit(worker);

            // Save the return value
            TypeReference voidType = module.Import(typeof(void));

            _surroundMethodBody.AddEpilog(worker);

            if (returnType != voidType)
            {
                worker.Emit(OpCodes.Ldloc, _parameters.ReturnValue);
            }

            worker.Emit(OpCodes.Ret);
        }
示例#10
0
        /// <summary>
        /// Emits the call to the <see cref="IAfterInvoke"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition targetMethod  = IL.GetMethod();
            TypeDefinition   declaringType = targetMethod.DeclaringType;
            ModuleDefinition module        = declaringType.Module;

            var getSurroundingClassImplementation = new GetSurroundingClassImplementation(_invocationInfo,
                                                                                          _surroundingClassImplementation,
                                                                                          _registryType.GetMethod(
                                                                                              "GetSurroundingImplementation"));

            // var classAroundInvoke = AroundInvokeRegistry.GetSurroundingImplementation(info);
            getSurroundingClassImplementation.Emit(IL);

            // classAroundInvoke.BeforeInvoke(info);
            Instruction skipInvoke = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation);
            IL.Emit(OpCodes.Brfalse, skipInvoke);

            MethodReference beforeInvoke = module.ImportMethod <IBeforeInvoke>("BeforeInvoke");

            // surroundingImplementation.BeforeInvoke(invocationInfo);
            IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, beforeInvoke);

            IL.Append(skipInvoke);

            // if (surroundingImplementation != null) {
            if (!targetMethod.HasThis)
            {
                return;
            }

            Instruction skipInvoke1 = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _surroundingImplementation);
            IL.Emit(OpCodes.Brfalse, skipInvoke1);

            MethodReference beforeInvoke1 = module.ImportMethod <IBeforeInvoke>("BeforeInvoke");

            // surroundingImplementation.BeforeInvoke(invocationInfo);
            IL.Emit(OpCodes.Ldloc, _surroundingImplementation);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Callvirt, beforeInvoke1);

            IL.Append(skipInvoke1);
            // }
        }
示例#11
0
        /// <summary>
        /// Emits a Console.WriteLine call using the current CilWorker.
        /// </summary>
        /// <param name="IL">The target CilWorker.</param>
        /// <param name="text">The text that will be written to the console.</param>
        public static void EmitWriteLine(this CilWorker IL, string text)
        {
            MethodBody       body          = IL.GetBody();
            MethodDefinition method        = body.Method;
            TypeDefinition   declaringType = method.DeclaringType;
            ModuleDefinition module        = declaringType.Module;

            MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine",
                                                                   BindingFlags.Public | BindingFlags.Static, null,
                                                                   new[] { typeof(string) }, null);

            IL.Emit(OpCodes.Ldstr, text);
            IL.Emit(OpCodes.Call, module.Import(writeLineMethod));
        }
示例#12
0
        private static void Emit(CilWorker IL, ModuleDefinition module,
                                 VariableDefinition surroundingImplementation,
                                 VariableDefinition invocationInfo,
                                 VariableDefinition returnValue)
        {
            var skipInvoke = IL.Create(OpCodes.Nop);

            var skipPrint = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
            IL.Emit(OpCodes.Brtrue, skipPrint);

            IL.Append(skipPrint);
            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
            IL.Emit(OpCodes.Brfalse, skipInvoke);

            var aroundInvoke = module.ImportMethod <IAfterInvoke>("AfterInvoke");

            IL.Emit(OpCodes.Ldloc, surroundingImplementation);
            IL.Emit(OpCodes.Ldloc, invocationInfo);
            IL.Emit(OpCodes.Ldloc, returnValue);
            IL.Emit(OpCodes.Callvirt, aroundInvoke);

            IL.Append(skipInvoke);
        }
示例#13
0
        /// <summary>
        /// Emits the instructions that obtain a class-level <see cref="IMethodReplacementProvider"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> instance that points to the instructions in the method body.</param>
        public void Emit(CilWorker IL)
        {
            ModuleDefinition module = IL.GetModule();
            MethodDefinition method = IL.GetMethod();

            MethodReference getProvider = _resolveGetProviderMethod(module);

            OpCode pushThis = method.HasThis ? OpCodes.Ldarg_0 : OpCodes.Ldnull;

            IL.Emit(pushThis);

            IL.Emit(OpCodes.Ldloc, _invocationInfo);
            IL.Emit(OpCodes.Call, getProvider);
            IL.Emit(OpCodes.Stloc, _classMethodReplacementProvider);
        }
示例#14
0
        private void ReconstructMethodArguments(CilWorker IL, MethodReference targetMethod)
        {
            if (targetMethod.HasThis)
            {
                IL.Emit(OpCodes.Ldloc, _target);
            }

            // Push the arguments back onto the stack
            foreach (ParameterReference param in targetMethod.Parameters)
            {
                IL.Emit(OpCodes.Ldloc, _currentArguments);
                IL.Emit(OpCodes.Callvirt, _popMethod);
                IL.Emit(OpCodes.Unbox_Any, param.ParameterType);
            }
        }
示例#15
0
        /// <summary>
        /// Saves the current method signature of a method into an array
        /// of <see cref="System.Type"/> objects. This can be used to determine the
        /// signature of methods with generic type parameters or methods that have
        /// parameters that are generic parameters specified by the type itself.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="method">The target method whose generic type arguments (if any) will be saved into the local variable .</param>
        /// <param name="module">The module that contains the host method.</param>
        /// <param name="parameterTypes">The local variable that will store the current method signature.</param>
        public static void SaveParameterTypes(this CilWorker IL, MethodReference method, ModuleDefinition module,
                                              VariableDefinition parameterTypes)
        {
            var getTypeFromHandle = module.ImportMethod <Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
            var parameterCount    = method.Parameters.Count;

            for (var index = 0; index < parameterCount; index++)
            {
                var current = method.Parameters[index];
                IL.Emit(OpCodes.Ldloc, parameterTypes);
                IL.Emit(OpCodes.Ldc_I4, index);
                IL.Emit(OpCodes.Ldtoken, current.ParameterType);
                IL.Emit(OpCodes.Call, getTypeFromHandle);
                IL.Emit(OpCodes.Stelem_Ref);
            }
        }
示例#16
0
        public void AddEpilog(CilWorker IL)
        {
            var skipEpilog = IL.Create(OpCodes.Nop);

            // if (!IsInterceptionDisabled && surroundingImplementation != null) {
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipEpilog);

            // surroundingImplementation.AfterInvoke(invocationInfo, returnValue);
            var emitAfterInvoke = new EmitAfterInvoke(_surroundingImplementation, _surroundingClassImplementation, _invocationInfo, _returnValue);

            emitAfterInvoke.Emit(IL);

            // }
            IL.Append(skipEpilog);
        }
示例#17
0
        /// <summary>
        /// Saves the current <see cref="IExceptionHandlerInfo"/> instance.
        /// </summary>
        /// <param name="targetMethod">The target method.</param>
        /// <param name="emitter">The <see cref="IEmitInvocationInfo"/> instance that will emit the current method context.</param>
        private void SaveExceptionInfo(MethodDefinition targetMethod, IEmitInvocationInfo emitter)
        {
            CilWorker        IL     = targetMethod.GetILGenerator();
            ModuleDefinition module = IL.GetModule();

            emitter.Emit(targetMethod, targetMethod, _invocationInfo);
            IL.Emit(OpCodes.Ldloc, _exception);
            IL.Emit(OpCodes.Ldloc, _invocationInfo);

            MethodReference exceptionInfoConstructor = module.ImportConstructor <ExceptionHandlerInfo>(
                typeof(Exception),
                typeof(IInvocationInfo));

            IL.Emit(OpCodes.Newobj, exceptionInfoConstructor);
            IL.Emit(OpCodes.Stloc, _exceptionInfo);

            TypeReference returnType = targetMethod.ReturnType.ReturnType;

            if (returnType == _voidType || _returnValue == null)
            {
                return;
            }

            // exceptionInfo.ReturnValue = returnValue;
            MethodReference setReturnValue = module.ImportMethod <IExceptionHandlerInfo>("set_ReturnValue");

            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Ldloc, _returnValue);
            IL.Emit(OpCodes.Callvirt, setReturnValue);
        }
示例#18
0
        /// <summary>
        /// Stores the <paramref name="param">current parameter value</paramref>
        /// into the array of method <paramref name="arguments"/>.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="arguments">The local variable that will store the method arguments.</param>
        /// <param name="index">The array index that indicates where the parameter value will be stored in the array of arguments.</param>
        /// <param name="param">The current argument value being stored.</param>
        private static void PushParameter(this CilWorker IL, int index, VariableDefinition arguments,
                                          ParameterDefinition param)
        {
            var parameterType = param.ParameterType;

            IL.Emit(OpCodes.Ldloc, arguments);
            IL.Emit(OpCodes.Ldc_I4, index);

            // Zero out the [out] parameters
            if (param.IsOut || param.IsByRef())
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stelem_Ref);
                return;
            }

            IL.Emit(OpCodes.Ldarg, param);

            if (parameterType.IsValueType || parameterType is GenericParameter)
            {
                IL.Emit(OpCodes.Box, param.ParameterType);
            }

            IL.Emit(OpCodes.Stelem_Ref);
        }
示例#19
0
        private void SaveConstructorArgument(CilWorker IL, ParameterDefinition param)
        {
            // Box the type if necessary
            var parameterType = param.ParameterType;

            if (parameterType.IsValueType || parameterType is GenericParameter)
            {
                IL.Emit(OpCodes.Box, parameterType);
            }

            // Save the current argument
            IL.Emit(OpCodes.Stloc, _currentArgument);

            // Add the item to the item to the collection
            IL.Emit(OpCodes.Ldloc, _constructorArguments);
            IL.Emit(OpCodes.Ldloc, _currentArgument);
            IL.Emit(OpCodes.Callvirt, _addMethod);
        }
示例#20
0
        /// <summary>
        /// Creates a property getter method implementation with the
        /// <paramref name="propertyType"/> as the return type.
        /// </summary>
        /// <param name="propertyType">Represents the <see cref="TypeReference">return type</see> for the getter method.</param>
        /// <param name="getterName">The getter method name.</param>
        /// <param name="attributes">The method attributes associated with the getter method.</param>
        /// <param name="backingField">The field that will store the instance that the getter method will retrieve.</param>
        /// <returns>A <see cref="MethodDefinition"/> representing the getter method itself.</returns>
        private static MethodDefinition AddPropertyGetter(TypeReference propertyType,
                                                          string getterName, MethodAttributes attributes,
                                                          FieldReference backingField)
        {
            var getter = new MethodDefinition(getterName, attributes, propertyType)
            {
                IsPublic       = true,
                ImplAttributes = (MethodImplAttributes.Managed | MethodImplAttributes.IL)
            };

            CilWorker IL = getter.GetILGenerator();

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Ldfld, backingField);
            IL.Emit(OpCodes.Ret);

            return(getter);
        }
示例#21
0
        /// <summary>
        /// Emits the instructions that obtain the <see cref="IMethodReplacementProvider"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> instance.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method        = _hostMethod;
            TypeDefinition   declaringType = method.DeclaringType;
            ModuleDefinition module        = declaringType.Module;

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
                return;
            }

            MethodReference getProvider = _resolveGetProviderMethod(module);

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getProvider);
            IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
        }
示例#22
0
        /// <summary>
        /// Emits the instructions that obtain the <see cref="IMethodReplacementProvider"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> instance.</param>
        public void Emit(CilWorker IL)
        {
            var method        = _hostMethod;
            var declaringType = method.DeclaringType;
            var module        = declaringType.Module;

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
                return;
            }

            var getProvider = _resolveGetProviderMethod(module);

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getProvider);
            IL.Emit(OpCodes.Stloc, _methodReplacementProvider);
        }
示例#23
0
        /// <summary>
        /// Saves the generic type arguments that were used to construct the method.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="method">The target method whose generic type arguments (if any) will be saved into the <paramref name="typeArguments">local variable</paramref>.</param>
        /// <param name="module">The module that contains the host method.</param>
        /// <param name="typeArguments">The local variable that will store the resulting array of <see cref="Type"/> objects.</param>
        public static void PushGenericArguments(this CilWorker IL, IGenericParameterProvider method,
                                                ModuleDefinition module, VariableDefinition typeArguments)
        {
            var getTypeFromHandle     = module.ImportMethod <Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
            var genericParameterCount = method.GenericParameters.Count;

            var genericParameters = method.GenericParameters;

            for (var index = 0; index < genericParameterCount; index++)
            {
                var current = genericParameters[index];

                IL.Emit(OpCodes.Ldloc, typeArguments);
                IL.Emit(OpCodes.Ldc_I4, index);
                IL.Emit(OpCodes.Ldtoken, current);
                IL.Emit(OpCodes.Call, getTypeFromHandle);
                IL.Emit(OpCodes.Stelem_Ref);
            }
        }
        public void Emit(CilWorker IL)
        {
            var method = IL.GetMethod();
            var module = IL.GetModule();

            // var aroundInvokeProvider = this.AroundInvokeProvider;
            var getAroundInvokeProvider = module.ImportMethod <IModifiableType>("get_AroundInvokeProvider");

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
                return;
            }

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getAroundInvokeProvider);
            IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
        }
示例#25
0
        /// <summary>
        /// Emits the call to obtain the <see cref="IAroundInvokeProvider"/> instance.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param>
        public void Emit(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();
            ModuleDefinition module = IL.GetModule();

            // var aroundInvokeProvider = this.AroundInvokeProvider;
            string          propertyName            = string.Format("get_{0}", _providerName);
            MethodReference getAroundInvokeProvider = module.ImportMethod <IAroundInvokeHost>(propertyName);

            if (!method.HasThis)
            {
                IL.Emit(OpCodes.Ldnull);
                IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
                return;
            }

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Callvirt, getAroundInvokeProvider);
            IL.Emit(OpCodes.Stloc, _aroundInvokeProvider);
        }
示例#26
0
        private void GetInstanceProvider(CilWorker IL)
        {
            var skipInstanceProvider = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, _hostInterfaceType);
            IL.Emit(OpCodes.Brfalse, skipInstanceProvider);
            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Isinst, _hostInterfaceType);
            IL.Emit(OpCodes.Callvirt, _getProvider);
            IL.Emit(OpCodes.Stloc, _instanceProvider);

            IL.Emit(OpCodes.Ldloc, _instanceProvider);
            IL.Emit(OpCodes.Brtrue, skipInstanceProvider);

            IL.Append(skipInstanceProvider);
        }
示例#27
0
        /// <summary>
        /// Creates a property setter method implementation with the
        /// <paramref name="propertyType"/> as the setter parameter.
        /// </summary>
        /// <param name="propertyType">Represents the <see cref="TypeReference">parameter type</see> for the setter method.</param>
        /// <param name="attributes">The method attributes associated with the setter method.</param>
        /// <param name="backingField">The field that will store the instance for the setter method.</param>
        /// <param name="setterName">The method name of the setter method.</param>
        /// <param name="voidType">The <see cref="TypeReference"/> that represents <see cref="Void"/>.</param>
        /// <returns>A <see cref="MethodDefinition"/> that represents the setter method itself.</returns>
        private static MethodDefinition AddPropertySetter(TypeReference propertyType, MethodAttributes attributes,
                                                          FieldReference backingField, string setterName,
                                                          TypeReference voidType)
        {
            var setter = new MethodDefinition(setterName, attributes, voidType)
            {
                IsPublic       = true,
                ImplAttributes = (MethodImplAttributes.Managed | MethodImplAttributes.IL)
            };

            setter.Parameters.Add(new ParameterDefinition(propertyType));

            CilWorker IL = setter.GetILGenerator();

            IL.Emit(OpCodes.Ldarg_0);
            IL.Emit(OpCodes.Ldarg_1);
            IL.Emit(OpCodes.Stfld, backingField);
            IL.Emit(OpCodes.Ret);

            return(setter);
        }
示例#28
0
        /// <summary>
        /// Pushes the arguments of a method onto the stack.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param>
        /// <param name="module">The module that contains the host method.</param>
        /// <param name="method">The target method.</param>
        /// <param name="arguments">The <see cref="VariableDefinition">local variable</see> that will hold the array of arguments.</param>
        public static void PushArguments(this CilWorker IL, IMethodSignature method, ModuleDefinition module, VariableDefinition arguments)
        {
            var objectType     = module.ImportType(typeof(object));
            int parameterCount = method.Parameters.Count;

            IL.Emit(OpCodes.Ldc_I4, parameterCount);
            IL.Emit(OpCodes.Newarr, objectType);
            IL.Emit(OpCodes.Stloc, arguments);

            if (parameterCount == 0)
            {
                return;
            }

            var index = 0;

            foreach (ParameterDefinition param in method.Parameters)
            {
                IL.PushParameter(index++, arguments, param);
            }
        }
        private static void GetMethodReplacementInstance(MethodDefinition method,
                                                         CilWorker IL,
                                                         VariableDefinition methodReplacement,
                                                         VariableDefinition methodReplacementProvider, VariableDefinition invocationInfo)
        {
            var declaringType = method.DeclaringType;
            var module        = declaringType.Module;
            var pushInstance  = method.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull);

            var getReplacement = module.ImportMethod <IMethodReplacementProvider>("GetMethodReplacement");

            IL.Emit(OpCodes.Ldloc, methodReplacementProvider);

            var skipGetMethodReplacement = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Brfalse, skipGetMethodReplacement);
            IL.Emit(OpCodes.Ldloc, methodReplacementProvider);

            IL.Append(pushInstance);
            IL.Emit(OpCodes.Ldloc, invocationInfo);
            IL.Emit(OpCodes.Callvirt, getReplacement);
            IL.Emit(OpCodes.Stloc, methodReplacement);

            IL.Append(skipGetMethodReplacement);
        }
示例#30
0
        private void SaveConstructorArguments(CilWorker IL, ParameterDefinitionCollection parameters)
        {
            var parameterCount = parameters.Count;

            IL.Emit(OpCodes.Newobj, _objectListCtor);
            IL.Emit(OpCodes.Stloc, _constructorArguments);

            var index = parameterCount - 1;

            while (index >= 0)
            {
                var param = parameters[index];

                SaveConstructorArgument(IL, param);

                index--;
            }

            // Reverse the constructor arguments so that they appear in the correct order
            IL.Emit(OpCodes.Ldloc, _constructorArguments);
            IL.Emit(OpCodes.Callvirt, _reverseMethod);
        }