void DefineMethod(TypeBuilder typeBuilder, MethodInfo wrapperMethodInfo, MemberInfo baseMemberInfo, List <FieldInfo> ctorInfos, List <object> ctorArgs, Type sourceType, FieldBuilder sourceObjectField, BaseReflectionHelperInterfaceWrapperSetting setting, MemberInfoKind method, bool isStatic) { var sourceMethodIsInterface = GetIsInterface(setting, wrapperMethodInfo.Name, baseMemberInfo ?? wrapperMethodInfo); var sourceMethodName = GetTargetName(wrapperMethodInfo.Name, setting, method, baseMemberInfo ?? wrapperMethodInfo); var sourceMethodBindingFalgs = setting.GetBindingFlags(baseMemberInfo, wrapperMethodInfo) | (isStatic ? BindingFlags.Static : 0); var sourceMethodInfo = (sourceMethodIsInterface ? sourceType.GetInterfaces() : FlatternType(sourceType, false)).Select(x => GetMethod(x, sourceMethodName, sourceMethodBindingFalgs, wrapperMethodInfo)).FirstOrDefault(x => x != null); FieldBuilder fieldInfo = null; if (sourceMethodInfo != null) { fieldInfo = typeBuilder.DefineField("field" + wrapperMethodInfo.Name, sourceMethodInfo.GetType(), FieldAttributes.Private); ctorInfos.Add(fieldInfo); ctorArgs.Add(sourceMethodInfo); } var parameterTypes = wrapperMethodInfo.GetParameters().Select(x => x.ParameterType).ToArray(); var genericParameters = wrapperMethodInfo.GetGenericArguments(); var methodBuilder = typeBuilder.DefineMethod(wrapperMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, wrapperMethodInfo.ReturnType, parameterTypes); GenericTypeParameterBuilder[] genericParameterBuilders = null; if (genericParameters.Length > 0) { genericParameterBuilders = methodBuilder.DefineGenericParameters(genericParameters.Select(x => x.Name).ToArray()); } Type[] updatedParameterTypes = new Type[parameterTypes.Length]; for (int i = 0; i < parameterTypes.Length; i++) { var currentType = parameterTypes[i]; if (ShouldWrapType(currentType)) { updatedParameterTypes[i] = currentType.IsByRef ? tpObject : typeof(object); } else { updatedParameterTypes[i] = currentType; } } var ilGenerator = methodBuilder.GetILGenerator(); var returnType = wrapperMethodInfo.ReturnType; var wrapReturnType = ShouldWrapType(returnType); var unwrappedReturnTupe = wrapReturnType ? typeof(object) : returnType; var useTuple = false; var delegateType = ReflectionHelper.MakeGenericDelegate(updatedParameterTypes, ref unwrappedReturnTupe, isStatic ? null : typeof(object), out useTuple); var delegateInvoke = delegateType.GetMethod("Invoke"); LocalBuilder tupleLocalBuilder = null; if (useTuple) { tupleLocalBuilder = ilGenerator.DeclareLocal(unwrappedReturnTupe); } var fallbackMode = sourceMethodInfo == null; if (fallbackMode) { if (!PrepareFallback(typeBuilder, wrapperMethodInfo, ctorInfos, ctorArgs, setting, ilGenerator, method, delegateInvoke, isStatic, baseMemberInfo)) { ilGenerator.Emit(OpCodes.Ret); return; } } else { ilGenerator.Emit(OpCodes.Ldarg_0); Ldfld(ilGenerator, fieldInfo); TypeOf(ilGenerator, sourceType); TypeOf(ilGenerator, delegateType); ilGenerator.Emit(useTuple ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); var methodInfo = ReflectionHelperInterfaceWrapper.GetDelegateMethodInfo; if (genericParameters.Length > 0) { ilGenerator.Emit(OpCodes.Ldc_I4, genericParameters.Length); ilGenerator.Emit(OpCodes.Newarr, typeof(Type)); for (var i = 0; i < genericParameters.Length; i++) { ilGenerator.Emit(OpCodes.Dup); ilGenerator.Emit(OpCodes.Ldc_I4, i); TypeOf(ilGenerator, genericParameterBuilders[i]); ilGenerator.Emit(OpCodes.Stelem_Ref); } methodInfo = ReflectionHelperInterfaceWrapper.GetGenericDelegateMethodInfo; } EmitCall(ilGenerator, OpCodes.Call, methodInfo, null); } if (!isStatic) { Ldfld(ilGenerator, sourceObjectField); } for (byte i = 0; i < updatedParameterTypes.Length; i++) { var paramType = updatedParameterTypes[i]; if (parameterTypes[i] != updatedParameterTypes[i]) { ilGenerator.Emit(OpCodes.Ldarg, i + 1); if (paramType.IsByRef) { LSTind(ilGenerator, paramType.GetElementType(), false); } EmitCall(ilGenerator, OpCodes.Call, ReflectionHelperInterfaceWrapper.UnwrapMethodInfo, null); } else { ilGenerator.Emit(OpCodes.Ldarg, i + 1); if (paramType.IsByRef) { LSTind(ilGenerator, paramType.GetElementType(), false); } } } EmitCall(ilGenerator, OpCodes.Call, delegateInvoke, null); if (useTuple) { SyncTupleItems(updatedParameterTypes.Select((x, i) => new Tuple <int, Type, Type>(i, x, parameterTypes[i])).Where(x => x.Item2.IsByRef), unwrappedReturnTupe, wrapperMethodInfo.ReturnType != typeof(void), ilGenerator, tupleLocalBuilder, typeBuilder); } if (wrapReturnType) { TypeOf(ilGenerator, returnType); EmitCall(ilGenerator, OpCodes.Call, ReflectionHelperInterfaceWrapper.WrapMethodInfo, null); } ilGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, wrapperMethodInfo); }
void DefineFieldGetterOrSetter(TypeBuilder typeBuilder, PropertyInfo propertyInfo, MethodInfo wrapperMethodInfo, List <FieldInfo> ctorInfos, List <object> ctorArgs, Type sourceType, FieldBuilder sourceObjectField, BaseReflectionHelperInterfaceWrapperSetting setting, MemberInfoKind method, bool isStatic) { var sourceFieldInfo = sourceType.GetField(GetTargetName(propertyInfo.Name, setting, MemberInfoKind.Method, propertyInfo), setting.GetBindingFlags(wrapperMethodInfo, propertyInfo) | (isStatic ? BindingFlags.Static : 0)); FieldBuilder fieldInfo = null; if (sourceFieldInfo != null) { fieldInfo = typeBuilder.DefineField("field" + wrapperMethodInfo.Name, sourceFieldInfo.GetType(), FieldAttributes.Private); ctorInfos.Add(fieldInfo); ctorArgs.Add(sourceFieldInfo); } var parameterTypes = wrapperMethodInfo.GetParameters().Select(x => x.ParameterType).ToArray(); var methodBuilder = typeBuilder.DefineMethod(wrapperMethodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, wrapperMethodInfo.ReturnType, parameterTypes); var ilGenerator = methodBuilder.GetILGenerator(); var returnType = wrapperMethodInfo.ReturnType; bool wrapReturnType = method == MemberInfoKind.PropertyGetter && ShouldWrapType(returnType); bool wrapParameterType = method == MemberInfoKind.PropertySetter && !wrapReturnType && ShouldWrapType(parameterTypes[0]); Type unwrappedReturnType, unwrappedParameterType; Type[] unwrappedParameterTypes = parameterTypes; unwrappedReturnType = wrapReturnType ? typeof(object) : returnType; if (wrapParameterType) { unwrappedParameterType = sourceFieldInfo.FieldType; unwrappedParameterTypes = new Type[] { unwrappedParameterType }; } else { unwrappedParameterType = null; } var useTuple = false; var delegateType = ReflectionHelper.MakeGenericDelegate(unwrappedParameterTypes, ref unwrappedReturnType, isStatic ? null : typeof(object), out useTuple); var delegateInvoke = delegateType.GetMethod("Invoke"); var fallbackMode = sourceFieldInfo == null; if (fallbackMode) { if (!PrepareFallback(typeBuilder, wrapperMethodInfo, ctorInfos, ctorArgs, setting, ilGenerator, method, delegateInvoke, isStatic, propertyInfo)) { ilGenerator.Emit(OpCodes.Ret); return; } } else { ilGenerator.Emit(OpCodes.Ldarg_0); Ldfld(ilGenerator, fieldInfo); TypeOf(ilGenerator, delegateType); TypeOf(ilGenerator, typeof(object)); if (wrapParameterType || wrapReturnType) { TypeOf(ilGenerator, typeof(object)); } else { TypeOf(ilGenerator, sourceFieldInfo.FieldType); } if (isStatic) { ilGenerator.Emit(OpCodes.Ldc_I4_1); } else { ilGenerator.Emit(OpCodes.Ldc_I4_0); } EmitCall(ilGenerator, OpCodes.Call, method == MemberInfoKind.PropertyGetter ? ReflectionHelperInterfaceWrapper.GetFieldGetterMethodInfo : ReflectionHelperInterfaceWrapper.GetFieldSetterMethodInfo, null); } if (!isStatic) { Ldfld(ilGenerator, sourceObjectField); } for (byte i = 0; i < parameterTypes.Length; i++) { ilGenerator.Emit(OpCodes.Ldarg, i + 1); if (wrapParameterType) { EmitCall(ilGenerator, OpCodes.Call, ReflectionHelperInterfaceWrapper.UnwrapMethodInfo, null); } } EmitCall(ilGenerator, OpCodes.Call, delegateInvoke, null); if (wrapReturnType) { TypeOf(ilGenerator, returnType); EmitCall(ilGenerator, OpCodes.Call, ReflectionHelperInterfaceWrapper.WrapMethodInfo, null); } ilGenerator.Emit(OpCodes.Ret); typeBuilder.DefineMethodOverride(methodBuilder, tWrapper.GetMethod(wrapperMethodInfo.Name)); }