Exemple #1
0
        private static Hashtable GetTargetMethods(Object BaseObject)
        {
            Type      baseType = BaseObject.GetType();
            Hashtable retVal   = new Hashtable();

            foreach (Type itf in baseType.GetInterfaces())
            {
                InterfaceMapping imap = baseType.GetInterfaceMap(itf);

                for (int i = 0; i < imap.InterfaceMethods.Length; i++)
                {
                    MethodInfo trueTarget;

                    if (imap.TargetMethods[i].IsPublic)
                    {
                        //  We can invoke the true target
                        //  so the mapping will be directly to the target method.
                        //  Note that I don't care if it's final or not.
                        trueTarget = imap.TargetMethods[i];
                    }
                    else
                    {
                        trueTarget = imap.InterfaceMethods[i];
                    }

                    MethodMappings itfMM = (MethodMappings)retVal[trueTarget];

                    if (null == itfMM)
                    {
                        itfMM = new MethodMappings(trueTarget, true);
                        retVal.Add(trueTarget, itfMM);
                    }

                    itfMM.MappedMethods.Add(imap.InterfaceMethods[i]);
                }
            }

            foreach (MethodInfo mi in baseType.GetMethods())
            {
                if (mi.IsPublic && mi.IsVirtual && !mi.IsFinal)
                {
                    //  Let's see if we already have it
                    //  from the interface mapping.
                    MethodMappings baseMM = (MethodMappings)retVal[mi];

                    if (null == baseMM)
                    {
                        //  This method doesn't override
                        //  any itf. methods, so add it.
                        baseMM = new MethodMappings(mi, false);
                        retVal.Add(mi, baseMM);
                        baseMM.MappedMethods.Add(mi);
                    }
                }
            }

            return(retVal);
        }
Exemple #2
0
        private static void BuildTargetMethods(TypeBuilder BaseProxy, MethodInfo InvokeMethod,
                                               FieldBuilder WrappedObject,
                                               Hashtable TargetMethods)
        {
            #region Variable Declarations

            Type[]           argTypes  = null;
            LocalBuilder     argValues = null;
            MethodAttributes methodAttribs;
            LocalBuilder     methodCxtInfo    = null;
            MethodInfo       mi               = null;
            Type             paramRetType     = null;
            String           paramRetTypeName = null;
            Type             paramType        = null;
            String           paramTypeName    = null;
            ParameterInfo    pi               = null;
            MethodBuilder    proxyMethod      = null;
            ILGenerator      proxyMthIL       = null;
            LocalBuilder     retVal           = null;
            LocalBuilder     targetMethod     = null;
            LocalBuilder     tempRetVal       = null;
            LocalBuilder     wrappedType      = null;

            #endregion

            /*
             * methodAttribs = MethodAttributes.HideBySig |
             * MethodAttributes.NewSlot | MethodAttributes.Virtual |
             * MethodAttributes.Private;
             */

            methodAttribs = MethodAttributes.HideBySig |
                            MethodAttributes.Virtual |
                            MethodAttributes.Private;

            foreach (DictionaryEntry de in TargetMethods)
            {
                mi = (MethodInfo)de.Key;

                argTypes = new Type[mi.GetParameters().Length];

                for (int i = 0; i < mi.GetParameters().Length; i++)
                {
                    argTypes[i] = mi.GetParameters()[i].ParameterType;
                }

                proxyMethod = BaseProxy.DefineMethod(mi.Name + mi.GetHashCode(),
                                                     methodAttribs, mi.ReturnType, argTypes);

                //  Determine if this method should override
                //  the mapped method (OverridesInterfaceMethods == false)
                //  or a number of itf. methods (OverridesInterfaceMethods == true)
                MethodMappings mm = (MethodMappings)de.Value;

                if (false == mm.OverridesInterfaceMethods)
                {
                    BaseProxy.DefineMethodOverride(proxyMethod, mi);
                }
                else
                {
                    for (int itfs = 0; itfs < mm.MappedMethods.Count; itfs++)
                    {
                        MethodInfo itfMth =
                            (MethodInfo)mm.MappedMethods[itfs];
                        BaseProxy.DefineMethodOverride(proxyMethod, itfMth);
                    }
                }

                proxyMthIL = proxyMethod.GetILGenerator();

                //  These are always there.
                argValues     = proxyMthIL.DeclareLocal(typeof(Object[]));
                methodCxtInfo = proxyMthIL.DeclareLocal(typeof(MethodContextInfo));
                targetMethod  = proxyMthIL.DeclareLocal(typeof(MethodInfo));
                wrappedType   = proxyMthIL.DeclareLocal(typeof(Type));

                //  Check for a return value.
                if (typeof(void) != mi.ReturnType)
                {
                    tempRetVal = proxyMthIL.DeclareLocal(typeof(Object));
                    retVal     = proxyMthIL.DeclareLocal(mi.ReturnType);
                }

                proxyMthIL.Emit(OpCodes.Ldc_I4, mi.GetParameters().Length);
                proxyMthIL.Emit(OpCodes.Newarr, typeof(Object));

                //  Set up the arg array
                if (0 == mi.GetParameters().Length)
                {
                    //  Store in argValues - there's no values
                    //  to put into the array.
                    proxyMthIL.Emit(OpCodes.Stloc, argValues);
                }
                else
                {
                    proxyMthIL.Emit(OpCodes.Stloc, argValues);
                    for (int argLoad = 0; argLoad < mi.GetParameters().Length; argLoad++)
                    {
                        proxyMthIL.Emit(OpCodes.Ldloc, argValues);
                        proxyMthIL.Emit(OpCodes.Ldc_I4, argLoad);
                        proxyMthIL.Emit(OpCodes.Ldarg, argLoad + 1);
                        pi = mi.GetParameters()[argLoad];

                        paramTypeName = pi.ParameterType.ToString();
                        paramTypeName = paramTypeName.Replace("&", "");
                        paramType     = Type.GetType(paramTypeName);

                        if (pi.ParameterType.IsByRef)
                        {
                            proxyMthIL.Emit(OpCodes.Ldobj, paramType);
                        }

                        if (paramType.IsValueType)
                        {
                            proxyMthIL.Emit(OpCodes.Box, paramType);
                        }

                        proxyMthIL.Emit(OpCodes.Stelem_Ref);
                    }
                }

                //  Get the target method.
                proxyMthIL.Emit(OpCodes.Ldtoken, mi);
                proxyMthIL.Emit(OpCodes.Call,
                                typeof(MethodBase).GetMethod(GET_METHOD_FROM_HANDLE));
                proxyMthIL.Emit(OpCodes.Castclass,
                                typeof(MethodInfo));
                proxyMthIL.Emit(OpCodes.Stloc, targetMethod);

                //  Set up the method context object.
                proxyMthIL.Emit(OpCodes.Ldloca, methodCxtInfo);
                proxyMthIL.Emit(OpCodes.Ldarg_0);
                proxyMthIL.Emit(OpCodes.Ldfld, WrappedObject);
                proxyMthIL.Emit(OpCodes.Callvirt,
                                typeof(Object).GetMethod(GET_TYPE));
                proxyMthIL.Emit(OpCodes.Stloc, wrappedType);
                proxyMthIL.Emit(OpCodes.Ldloc, wrappedType);
                proxyMthIL.Emit(OpCodes.Callvirt,
                                typeof(Type).GetMethod(GET_ASSEMBLY_PROP));
                proxyMthIL.Emit(OpCodes.Callvirt,
                                typeof(Assembly).GetMethod(GET_NAME, Type.EmptyTypes));
                proxyMthIL.Emit(OpCodes.Ldloc, wrappedType);
                proxyMthIL.Emit(OpCodes.Callvirt,
                                typeof(Type).GetMethod(GET_FULL_NAME_PROP));
                proxyMthIL.Emit(OpCodes.Ldloc, targetMethod);
                proxyMthIL.Emit(OpCodes.Callvirt,
                                typeof(MemberInfo).GetMethod(GET_NAME_PROP));
                argTypes    = new Type[3];
                argTypes[0] = typeof(AssemblyName);
                argTypes[1] = typeof(String);
                argTypes[2] = typeof(String);
                proxyMthIL.Emit(OpCodes.Call,
                                typeof(MethodContextInfo).GetConstructor(argTypes));
                //  "invokeMethod()".
                proxyMthIL.Emit(OpCodes.Ldarg_0);
                proxyMthIL.Emit(OpCodes.Ldloc, targetMethod);
                proxyMthIL.Emit(OpCodes.Ldloca, argValues);
                proxyMthIL.Emit(OpCodes.Ldloc, methodCxtInfo);
                proxyMthIL.Emit(OpCodes.Call, InvokeMethod);

                //  Set the method value (if any exists).
                if (typeof(void) != mi.ReturnType)
                {
                    //  Need to be careful here.  If the return type
                    //  is null, then we leave retVal as-is.
                    Label retIsNull = proxyMthIL.DefineLabel();
                    proxyMthIL.Emit(OpCodes.Stloc, tempRetVal);
                    proxyMthIL.Emit(OpCodes.Ldloc, tempRetVal);
                    proxyMthIL.Emit(OpCodes.Brfalse, retIsNull);
                    proxyMthIL.Emit(OpCodes.Ldloc, tempRetVal);

                    if (mi.ReturnType.IsValueType)
                    {
                        //  Unbox whatever is on the stack.
                        proxyMthIL.Emit(OpCodes.Unbox, mi.ReturnType);
                        //  Note:  See pg. 72 of Partition III to see why
                        //  I chose the general ldobj over ldind.
                        proxyMthIL.Emit(OpCodes.Ldobj, mi.ReturnType);
                    }
                    else
                    {
                        proxyMthIL.Emit(OpCodes.Castclass, mi.ReturnType);
                    }

                    proxyMthIL.Emit(OpCodes.Stloc, retVal);
                    proxyMthIL.MarkLabel(retIsNull);
                }
                else
                {
                    proxyMthIL.Emit(OpCodes.Pop);
                }

                //  Move the ByRef or out arg values from the array
                //  to the arg values.
                foreach (ParameterInfo argValueByRef in mi.GetParameters())
                {
                    if (argValueByRef.ParameterType.IsByRef ||
                        argValueByRef.IsOut)
                    {
                        paramRetTypeName = argValueByRef.ParameterType.ToString();
                        paramRetTypeName = paramRetTypeName.Replace("&", "");
                        paramRetType     = Type.GetType(paramRetTypeName);
                        proxyMthIL.Emit(OpCodes.Ldarg, argValueByRef.Position + 1);
                        proxyMthIL.Emit(OpCodes.Ldloc, argValues);
                        proxyMthIL.Emit(OpCodes.Ldc_I4, argValueByRef.Position);
                        proxyMthIL.Emit(OpCodes.Ldelem_Ref);
                        if (paramRetType.IsValueType)
                        {
                            proxyMthIL.Emit(OpCodes.Unbox, paramRetType);
                            proxyMthIL.Emit(OpCodes.Ldobj, paramRetType);
                            proxyMthIL.Emit(OpCodes.Stobj, paramRetType);
                        }
                        else
                        {
                            if (paramRetType != typeof(Object))
                            {
                                proxyMthIL.Emit(OpCodes.Castclass, paramRetType);
                            }
                            proxyMthIL.Emit(OpCodes.Stind_Ref);
                        }
                    }
                }

                //  Finally...return.
                if (typeof(void) != mi.ReturnType)
                {
                    proxyMthIL.Emit(OpCodes.Ldloc, retVal);
                }

                proxyMthIL.Emit(OpCodes.Ret);
            }
        }