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); }