static string GetTargetName(string wrapperMethodInfo, BaseReflectionHelperInterfaceWrapperSetting setting, MemberInfoKind kind, MemberInfo memberInfo) { var result = setting.GetName(wrapperMethodInfo, memberInfo); if (kind == MemberInfoKind.PropertyGetter && !result.Split('.').Last().StartsWith("get_")) { return("get_" + result); } if (kind == MemberInfoKind.PropertySetter && !result.Split('.').Last().StartsWith("set_")) { return("set_" + result); } return(result); }
bool GetIsInterface(BaseReflectionHelperInterfaceWrapperSetting setting, string name, MemberInfo memberInfo) { return(setting.GetIsInterface(name, memberInfo)); }
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); }
bool PrepareFallback(TypeBuilder typeBuilder, MethodInfo wrapperMethodInfo, List <FieldInfo> ctorInfos, List <object> ctorArgs, BaseReflectionHelperInterfaceWrapperSetting setting, ILGenerator ilGenerator, MemberInfoKind infoKind, MethodInfo delegateInvoke, bool isStatic, MemberInfo baseInfo) { var fallbackMode = setting.GetFallbackMode(wrapperMethodInfo, baseInfo, tWrapper); if (fallbackMode == ReflectionHelperFallbackMode.Default) { fallbackMode = defaultFallbackMode; } if (fallbackMode == ReflectionHelperFallbackMode.AbortWrapping) { throw new MissingMemberException(String.Format("\r\nCannot bind the {0}.{1} with the source member\r\n", wrapperMethodInfo.DeclaringType, wrapperMethodInfo.Name)); } var fallback = setting.GetFallback(infoKind); if (fallback == null) { if (fallbackMode != ReflectionHelperFallbackMode.ThrowNotImplementedException) { throw new ArgumentException(String.Format("\r\nCannot bind the {0}.{1} with the source member.\r\nPlease check spelling or define the fallback method with the following signature: \r\n\t{2}.\r\n", wrapperMethodInfo.DeclaringType, wrapperMethodInfo.Name, delegateInvoke.ToString())); } if (!this.isStatic) { ilGenerator.Emit(OpCodes.Pop); } ilGenerator.ThrowException(typeof(NotImplementedException)); return(false); } var fallbackType = fallback.GetType(); if (fallbackMode != ReflectionHelperFallbackMode.FallbackWithoutValidation) { var fallbackInvoke = fallbackType.GetMethod("Invoke"); var currentParameters = fallbackInvoke.GetParameters(); var expectedParameters = delegateInvoke.GetParameters(); StringBuilder exceptionBuilder = new StringBuilder(); exceptionBuilder.AppendFormat("\r\nFallback method for the {0}.{1} has incorrect signature.\r\nExpected: {2};\r\nBut was: {3}.", wrapperMethodInfo.DeclaringType, wrapperMethodInfo.Name, delegateInvoke.ToString(), fallbackInvoke.ToString()); if (currentParameters.Length != expectedParameters.Length || !fallbackInvoke.ReturnType.IsAssignableFrom(delegateInvoke.ReturnType)) { throw new ArgumentException(exceptionBuilder.ToString() + "\r\n"); } bool shouldThrow = false; for (int i = 0; i < currentParameters.Length; i++) { var current = currentParameters[i]; var expected = expectedParameters[i]; if (current.ParameterType.IsAssignableFrom(expected.ParameterType)) { continue; } exceptionBuilder.AppendFormat("\r\n\tParameter at {0}:\r\n\t\tShould be assignable with: {1}\r\n\t\tBut was: {2}", i, expected.ParameterType, current.ParameterType); shouldThrow = true; } if (shouldThrow) { throw new ArgumentException(exceptionBuilder.ToString() + "\r\n"); } } var fallbackField = typeBuilder.DefineField("field" + wrapperMethodInfo.Name + "fallback", fallbackType, FieldAttributes.Private); ctorInfos.Add(fallbackField); ctorArgs.Add(fallback); Ldfld(ilGenerator, fallbackField); return(true); }
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)); }