Beispiel #1
0
        private static Type EnsureDelegateType(BuildContext context, MethodInfo method)
        {
            // The delegate should be defined as inner type of context.TypeBuilder.
            // It's possible, but we can not define and use newly defined type as Emit target in its owner type.
            // To solve this problem, we should create a top level delegate and make sure its name is unique.
            //
            string delegateName = context.TypeBuilder.TypeBuilder.FullName + "$" + method.Name + "$Delegate";
            Type   delegateType = (Type)context.Items[delegateName];

            if (delegateType == null)
            {
                ParameterInfo[] pi         = method.GetParameters();
                Type[]          parameters = new Type[pi.Length];

                for (int i = 0; i < pi.Length; i++)
                {
                    parameters[i] = pi[i].ParameterType;
                }

                const MethodImplAttributes mia = MethodImplAttributes.Runtime | MethodImplAttributes.Managed;
                const MethodAttributes     ma  = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual;

                TypeBuilderHelper delegateBuilder = context.AssemblyBuilder.DefineType(delegateName,
                                                                                       TypeAttributes.Class | TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.AutoClass,
                                                                                       typeof(MulticastDelegate));

                // Create constructor
                //
                ConstructorBuilderHelper ctorBuilder = delegateBuilder.DefineConstructor(
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, CallingConventions.Standard,
                    typeof(object), typeof(IntPtr));
                ctorBuilder.ConstructorBuilder.SetImplementationFlags(mia);

                MethodBuilderHelper methodBuilder;

                // Define the BeginInvoke method for the delegate
                //
                Type[] beginParameters = new Type[parameters.Length + 2];

                Array.Copy(parameters, 0, beginParameters, 0, parameters.Length);
                beginParameters[parameters.Length]     = typeof(AsyncCallback);
                beginParameters[parameters.Length + 1] = typeof(object);

                methodBuilder = delegateBuilder.DefineMethod("BeginInvoke", ma, typeof(IAsyncResult), beginParameters);
                methodBuilder.MethodBuilder.SetImplementationFlags(mia);

                // Define the EndInvoke method for the delegate
                //
                methodBuilder = delegateBuilder.DefineMethod("EndInvoke", ma, method.ReturnType, typeof(IAsyncResult));
                methodBuilder.MethodBuilder.SetImplementationFlags(mia);

                // Define the Invoke method for the delegate
                //
                methodBuilder = delegateBuilder.DefineMethod("Invoke", ma, method.ReturnType, parameters);
                methodBuilder.MethodBuilder.SetImplementationFlags(mia);

                context.Items[delegateName] = delegateType = delegateBuilder.Create();
            }

            return(delegateType);
        }