EventSinkHelperWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / InteropServices / TCEAdapterGen / EventSinkHelperWriter.cs / 1 / 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;
    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();
                    BCLDebug.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" );
            BCLDebug.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
                            BCLDebug.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 );
            BCLDebug.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; 
    } 
}
                        

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