EventSinkHelperWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / InteropServices / TCEAdapterGen / EventSinkHelperWriter.cs / 1305376 / EventSinkHelperWriter.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
namespace System.Runtime.InteropServices.TCEAdapterGen {
    using System.Runtime.InteropServices; 
    using System; 
    using System.Reflection;
    using System.Reflection.Emit; 
    using System.Collections;
    using System.Diagnostics.Contracts;
    internal class EventSinkHelperWriter
    { 
        public static readonly String GeneratedTypeNamePostfix = "_SinkHelper";
 
        public EventSinkHelperWriter( ModuleBuilder OutputModule, Type InputType, Type EventItfType ) 
        {
            m_InputType = InputType; 
            m_OutputModule = OutputModule;
            m_EventItfType = EventItfType;
        }
 
        public Type Perform()
        { 
            // Create the output Type. 
            Type[] aInterfaces = new Type[1];
            aInterfaces[0] = m_InputType; 
            String strFullName = null;
            String strNameSpace = NameSpaceExtractor.ExtractNameSpace( m_EventItfType.FullName );

            if (strNameSpace != "") 
                strFullName = strNameSpace  + ".";
 
            strFullName += m_InputType.Name + GeneratedTypeNamePostfix; 
            TypeBuilder OutputTypeBuilder = TCEAdapterGenerator.DefineUniqueType(
                                                             strFullName, 
                                                             TypeAttributes.Sealed | TypeAttributes.Public,
                                                             null,
                                                             aInterfaces,
                                                             m_OutputModule 
                                                            );
            // Hide the _SinkProvider interface 
            TCEAdapterGenerator.SetHiddenAttribute(OutputTypeBuilder); 

            // Set the class interface to none. 
            TCEAdapterGenerator.SetClassInterfaceTypeToNone(OutputTypeBuilder);

            // Retrieve the property methods on the input interface and give them a dummy implementation.
            MethodInfo[] pMethods = TCEAdapterGenerator.GetPropertyMethods(m_InputType); 
            foreach (MethodInfo method in pMethods)
            { 
                DefineBlankMethod(OutputTypeBuilder, method); 
            }
 
            // Retrieve the non-property methods on the input interface.
            MethodInfo[] aMethods = TCEAdapterGenerator.GetNonPropertyMethods(m_InputType);

            // Allocate an array to contain the delegate fields. 
            FieldBuilder[] afbDelegates = new FieldBuilder[aMethods.Length];
            // Process all the methods on the input interface. 
            for ( int cMethods = 0; cMethods < aMethods.Length; cMethods++ ) 
            {
                if ( m_InputType == aMethods[cMethods].DeclaringType ) 
                {
                    // Retrieve the delegate type from the add_XXX method.
                    MethodInfo AddMeth = m_EventItfType.GetMethod( "add_" + aMethods[cMethods].Name );
                    ParameterInfo[] aParams = AddMeth.GetParameters(); 
                    Contract.Assert(aParams.Length == 1, "All event interface methods must take a single delegate derived type and have a void return type");
                    Type DelegateCls = aParams[0].ParameterType; 
 
                    // Define the delegate instance field.
                    afbDelegates[cMethods] = OutputTypeBuilder.DefineField( 
                                                  "m_" + aMethods[cMethods].Name + "Delegate",
                                                  DelegateCls,
                                                  FieldAttributes.Public
                                                 ); 

                    // Define the event method itself. 
                    DefineEventMethod( OutputTypeBuilder, aMethods[cMethods], DelegateCls, afbDelegates[cMethods] ); 
                }
            } 

            // Create the cookie field.
            FieldBuilder fbCookie = OutputTypeBuilder.DefineField(
                                                  "m_dwCookie", 
                                                  typeof(Int32),
                                                  FieldAttributes.Public 
                                                 ); 

            // Define the constructor. 
            DefineConstructor( OutputTypeBuilder, fbCookie, afbDelegates );

            return OutputTypeBuilder.CreateType();
        } 

        private void DefineBlankMethod(TypeBuilder OutputTypeBuilder, MethodInfo Method) 
        { 
            ParameterInfo[] PIs = Method.GetParameters();
            Type[] parameters = new Type[PIs.Length]; 
            for (int i=0; i < PIs.Length; i++)
            {
                parameters[i] = PIs[i].ParameterType;
            } 

            MethodBuilder Meth = OutputTypeBuilder.DefineMethod(Method.Name, 
                                                                Method.Attributes & ~MethodAttributes.Abstract, 
                                                                Method.CallingConvention,
                                                                Method.ReturnType, 
                                                                parameters);

            ILGenerator il = Meth.GetILGenerator();
 
            AddReturn(Method.ReturnType, il, Meth);
 
            il.Emit(OpCodes.Ret); 
        }
 
        private void DefineEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo Method, Type DelegateCls, FieldBuilder fbDelegate )
        {
            // Retrieve the method info for the invoke method on the delegate.
            MethodInfo DelegateInvokeMethod = DelegateCls.GetMethod( "Invoke" ); 
            Contract.Assert(DelegateInvokeMethod != null, "Unable to find method Delegate.Invoke()");
 
            // Retrieve the return type. 
            Type ReturnType = Method.ReturnType;
 
            // Define the actual event method.
            ParameterInfo[] paramInfos = Method.GetParameters();
            Type[]          parameterTypes;
            if (paramInfos != null) 
            {
                parameterTypes = new Type[paramInfos.Length]; 
                for (int i = 0; i < paramInfos.Length; i++) 
                {
                    parameterTypes[i] = paramInfos[i].ParameterType; 
                }
            }
            else
                parameterTypes = null; 

            MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Virtual; 
            MethodBuilder Meth = OutputTypeBuilder.DefineMethod( Method.Name, 
                                                                 attr,
                                                                 CallingConventions.Standard, 
                                                                 ReturnType,
                                                                 parameterTypes);

            // We explicitly do not specify parameter name and attributes since this Type 
            // is not meant to be exposed to the user. It is only used internally to do the
            // connection point to TCE mapping. 
 
            ILGenerator il = Meth.GetILGenerator();
 
            // Create the exit branch.
            Label ExitLabel = il.DefineLabel();

            // Generate the code that verifies that the delegate is not null. 
            il.Emit( OpCodes.Ldarg, (short)0 );
            il.Emit( OpCodes.Ldfld, fbDelegate ); 
            il.Emit( OpCodes.Brfalse, ExitLabel ); 

            // The delegate is not NULL so we need to invoke it. 
            il.Emit( OpCodes.Ldarg, (short)0 );
            il.Emit( OpCodes.Ldfld, fbDelegate );

            // Generate the code to load the arguments before we call invoke. 
            ParameterInfo[] aParams = Method.GetParameters();
            for ( int cParams = 0; cParams < aParams.Length; cParams++ ) 
            { 
                il.Emit( OpCodes.Ldarg, (short)(cParams + 1) );
            } 

            // Generate a tail call to invoke. This will cause the callvirt to return
            // directly to the caller of the current method instead of actually coming
            // back to the current method and returning. This will cause the value returned 
            // from the call to the COM server to be returned to the caller of this method.
 
            il.Emit( OpCodes.Callvirt, DelegateInvokeMethod ); 
            il.Emit( OpCodes.Ret );
 
            // This is the label that will be jumped to if no delegate is present.
            il.MarkLabel( ExitLabel );

            AddReturn(ReturnType, il, Meth); 

            il.Emit( OpCodes.Ret ); 
 
        }
 
        private void AddReturn(Type ReturnType, ILGenerator il, MethodBuilder Meth)
        {
            // Place a dummy return value on the stack before we return.
            if ( ReturnType == typeof(void) ) 
            {
                // There is nothing to place on the stack. 
            } 
            else if ( ReturnType.IsPrimitive )
            { 
                switch (System.Type.GetTypeCode(ReturnType))
                {
                    case TypeCode.Boolean:
                    case TypeCode.Char: 
                    case TypeCode.Byte:
                    case TypeCode.SByte: 
                    case TypeCode.Int16: 
                    case TypeCode.UInt16:
                    case TypeCode.Int32: 
                    case TypeCode.UInt32:
                        il.Emit( OpCodes.Ldc_I4_0 );
                        break;
 
                    case TypeCode.Int64:
                    case TypeCode.UInt64: 
                        il.Emit( OpCodes.Ldc_I4_0 ); 
                        il.Emit( OpCodes.Conv_I8 );
                        break; 

                    case TypeCode.Single:
                        il.Emit( OpCodes.Ldc_R4, 0 );
                        break; 

                    case TypeCode.Double: 
                        il.Emit( OpCodes.Ldc_R4, 0 ); 
                        il.Emit( OpCodes.Conv_R8 );
                        break; 

                    default:
                        // "TypeCode" does not include IntPtr, so special case it.
                        if ( ReturnType == typeof(IntPtr) ) 
                            il.Emit( OpCodes.Ldc_I4_0 );
                        else 
                            Contract.Assert(false, "Unexpected type for Primitive type."); 
                        break;
                } 
            }
            else if ( ReturnType.IsValueType )
            {
                // Allocate stack space for the return value type.  Zero-init. 
                Meth.InitLocals = true;
                LocalBuilder ltRetVal = il.DeclareLocal( ReturnType ); 
 
                // Load the value class on the stack.
                il.Emit( OpCodes.Ldloc_S, ltRetVal ); 

            }
            else
            { 
                // The return type is a normal type.
                il.Emit( OpCodes.Ldnull ); 
            } 
        }
 
        private void DefineConstructor( TypeBuilder OutputTypeBuilder, FieldBuilder fbCookie, FieldBuilder[] afbDelegates )
        {
            // Retrieve the constructor info for the base classe's constructor.
            ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[0], null ); 
            Contract.Assert(DefaultBaseClsCons != null, "Unable to find the constructor for class " + m_InputType.Name);
 
            // Define the default constructor. 
            MethodBuilder Cons = OutputTypeBuilder.DefineMethod( ".ctor",
                                                                 MethodAttributes.Assembly | MethodAttributes.SpecialName, 
                                                                 CallingConventions.Standard,
                                                                 null,
                                                                 null);
 
            ILGenerator il = Cons.GetILGenerator();
 
            // Generate the code to call the constructor of the base class. 
            il.Emit( OpCodes.Ldarg, (short)0 );
            il.Emit( OpCodes.Call, DefaultBaseClsCons ); 

            // Generate the code to set the cookie field to 0.
            il.Emit( OpCodes.Ldarg, (short)0 );
            il.Emit( OpCodes.Ldc_I4, 0 ); 
            il.Emit( OpCodes.Stfld, fbCookie );
 
            // Generate the code to set all the delegates to NULL. 
            for ( int cDelegates = 0; cDelegates < afbDelegates.Length; cDelegates++ )
            { 
                if (afbDelegates[cDelegates] != null)
                {
                    il.Emit( OpCodes.Ldarg,(short)0 );
                    il.Emit( OpCodes.Ldnull ); 
                    il.Emit( OpCodes.Stfld, afbDelegates[cDelegates] );
                } 
            } 

            // Emit the return opcode. 
            il.Emit( OpCodes.Ret );

        }
 
        private Type m_InputType;
        private Type m_EventItfType; 
        private ModuleBuilder m_OutputModule; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK