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