コード例 #1
0
        /// <summary>
        /// Добавляет к типу прокси реализацию метода.
        /// </summary>
        /// <param name="method">Исходный метод.</param>
        /// <returns>Динамический метод прокси.</returns>
        private MethodBuilder ImplementMethod(MethodInfo method)
        {
            var parameters    = method.GetParameters();
            var paramTypes    = ParameterConverter.GetTypes(parameters);
            var proxiedMethod = DynamicTypeBuilder.DefineMethod(method.Name,
                                                                MethodAttributes.Public | MethodAttributes.Virtual,
                                                                method.ReturnType, paramTypes);

            MakeGeneric(method, proxiedMethod);

            var ilGenerator       = proxiedMethod.GetILGenerator();
            var parametersEmitter = new ParametersEmitter(ilGenerator, paramTypes);
            var packedArgsEmitter = new PackedArgumentsEmitter(ilGenerator);

            ilGenerator.Emit(OpCodes.Nop);

            packedArgsEmitter.EmitProxy();

            // Обобщенные параметры будут известны только во время вызова
            // поэтому заранее собрать делегат не выйдетю
            var methodLambda = method.ContainsGenericParameters
                ? new ExtendedMethodInfo(method, null)
                : new ExtendedMethodInfo(method, Expressions.CreateMethodCall(method));

            var token = _methodLinkStore.CreateToken(methodLambda);

            packedArgsEmitter.EmitMethodToken(token);

            var argumentsEmitter = packedArgsEmitter.EmitArguments(parameters, parametersEmitter);

            if (method.ContainsGenericParameters)
            {
                packedArgsEmitter.EmitGenericArguments(method.GetGenericArguments());
            }

            ilGenerator.Emit(OpCodes.Ldarg_0);
            ilGenerator.Emit(OpCodes.Ldfld, _invokeDelegateField);
            packedArgsEmitter.EmitLoad();
            ilGenerator.Emit(OpCodes.Call, MethodReferences.ActionOfObjectArrayInvoke);

            // Странный блок, не уверен что он нужен.
            for (var i = 0; i < parameters.Length; i++)
            {
                // ReSharper disable once InvertIf
                if (parameters[i].ParameterType.IsByRef)
                {
                    parametersEmitter.EmitBeginSet(i);
                    argumentsEmitter.EmitGet(i);
                    parametersEmitter.EmitEndSet(i, typeof(object));
                }
            }

            packedArgsEmitter.EmitReturnValue(method.ReturnType);

            DynamicTypeBuilder.DefineMethodOverride(proxiedMethod, method);
            return(proxiedMethod);
        }
コード例 #2
0
            public ArrayEmitter <object> EmitArguments(IReadOnlyList <ParameterInfo> parameters, ParametersEmitter parametersEmitter)
            {
                // object[] args = new object[paramCount];
                _ilGenerator.Emit(OpCodes.Nop);

                _internalEmitter.EmitBeginSet((int)PackedArgumentPosition.MethodArguments);

                var argsEmitter = new ArrayEmitter <object>(_ilGenerator, parameters.Count);

                for (var i = 0; i < parameters.Count; i++)
                {
                    if (parameters[i].IsOut)
                    {
                        continue;
                    }

                    // args[i] = argi;
                    argsEmitter.EmitBeginSet(i);
                    parametersEmitter.EmitGet(i);
                    argsEmitter.EmitEndSet(parameters[i].ParameterType);
                }

                argsEmitter.EmitLoad();

                _internalEmitter.EmitEndSet(typeof(object[]));

                return(argsEmitter);
            }