예제 #1
0
        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);
        }
예제 #2
0
        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));
        }