Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / BCL / System / Runtime / InteropServices / TCEAdapterGen / EventProviderWriter.cs / 1 / EventProviderWriter.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== namespace System.Runtime.InteropServices.TCEAdapterGen { using System.Runtime.InteropServices.ComTypes; using ubyte = System.Byte; using System; using System.Reflection; using System.Reflection.Emit; using System.Collections; using System.Threading; internal class EventProviderWriter { private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; public static readonly String GeneratedClassNamePostfix = ""; public EventProviderWriter( ModuleBuilder OutputModule, String strDestTypeName, Type EventItfType, Type SrcItfType, Type SinkHelperType ) { m_OutputModule = OutputModule; m_strDestTypeName = strDestTypeName; m_EventItfType = EventItfType; m_SrcItfType = SrcItfType; m_SinkHelperType = SinkHelperType; } public Type Perform() { // Create the event provider class. TypeBuilder OutputTypeBuilder = m_OutputModule.DefineType( m_strDestTypeName, TypeAttributes.Sealed | TypeAttributes.NotPublic, typeof(Object), new Type[]{m_EventItfType, typeof(IDisposable)} ); // Create the event source field. FieldBuilder fbCPC = OutputTypeBuilder.DefineField( "m_ConnectionPointContainer", typeof(IConnectionPointContainer), FieldAttributes.Private ); // Create array of event sink helpers. FieldBuilder fbSinkHelper = OutputTypeBuilder.DefineField( "m_aEventSinkHelpers", typeof(ArrayList), FieldAttributes.Private ); // Define the connection point field. FieldBuilder fbEventCP = OutputTypeBuilder.DefineField( "m_ConnectionPoint", typeof(IConnectionPoint), FieldAttributes.Private ); // Define the InitXXX method. MethodBuilder InitSrcItfMethodBuilder = DefineInitSrcItfMethod( OutputTypeBuilder, m_SrcItfType, fbSinkHelper, fbEventCP, fbCPC ); // Process all the methods in the event interface. MethodInfo[] aMethods = TCEAdapterGenerator.GetNonPropertyMethods(m_SrcItfType); for ( int cMethods = 0; cMethods < aMethods.Length; cMethods++ ) { if ( m_SrcItfType == aMethods[cMethods].DeclaringType ) { // Define the add_XXX method. MethodBuilder AddEventMethodBuilder = DefineAddEventMethod( OutputTypeBuilder, aMethods[cMethods], m_SinkHelperType, fbSinkHelper, fbEventCP, InitSrcItfMethodBuilder ); // Define the remove_XXX method. MethodBuilder RemoveEventMethodBuilder = DefineRemoveEventMethod( OutputTypeBuilder, aMethods[cMethods], m_SinkHelperType, fbSinkHelper, fbEventCP ); } } // Define the constructor. DefineConstructor( OutputTypeBuilder, fbCPC ); // Define the finalize method. MethodBuilder FinalizeMethod = DefineFinalizeMethod( OutputTypeBuilder, m_SinkHelperType, fbSinkHelper, fbEventCP ); // Define the Dispose method. DefineDisposeMethod( OutputTypeBuilder, FinalizeMethod); return OutputTypeBuilder.CreateType(); } private MethodBuilder DefineAddEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo SrcItfMethod, Type SinkHelperClass, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP, MethodBuilder mbInitSrcItf ) { Type[] aParamTypes; // Find the delegate on the event sink helper. FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" ); BCLDebug.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); BCLDebug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the sink helper's constructor. ConstructorInfo SinkHelperCons = SinkHelperClass.GetConstructor(EventProviderWriter.DefaultLookup | BindingFlags.NonPublic, null, new Type[0], null ); BCLDebug.Assert(SinkHelperCons != null, "Unable to find the constructor for the sink helper"); // Retrieve the IConnectionPoint.Advise method. MethodInfo CPAdviseMethod = typeof(IConnectionPoint).GetMethod( "Advise" ); BCLDebug.Assert(CPAdviseMethod != null, "Unable to find the method ConnectionPoint.Advise"); // Retrieve the ArrayList.Add method. aParamTypes = new Type[1]; aParamTypes[0] = typeof(Object); MethodInfo ArrayListAddMethod = typeof(ArrayList).GetMethod( "Add", aParamTypes, null ); BCLDebug.Assert(ArrayListAddMethod != null, "Unable to find the method ArrayList.Add"); // Retrieve the Monitor.Enter() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", aParamTypes, null ); BCLDebug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); BCLDebug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Define the add_XXX method. Type[] parameterTypes; parameterTypes = new Type[1]; parameterTypes[0] = DelegateField.FieldType; MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "add_" + SrcItfMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, null, parameterTypes ); ILGenerator il = Meth.GetILGenerator(); // Define a label for the m_IFooEventsCP comparision. Label EventCPNonNullLabel = il.DefineLabel(); // Declare the local variables. LocalBuilder ltSinkHelper = il.DeclareLocal( SinkHelperClass ); LocalBuilder ltCookie = il.DeclareLocal( typeof(Int32) ); // Generate the following code: // Monitor.Enter(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorEnterMethod ); // Generate the following code: // try { il.BeginExceptionBlock(); // Generate the following code: // if ( m_IFooEventsCP != null ) goto EventCPNonNullLabel; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Brtrue, EventCPNonNullLabel ); // Generate the following code: // InitIFooEvents(); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, mbInitSrcItf ); // Mark this as label to jump to if the CP is not null. il.MarkLabel( EventCPNonNullLabel ); // Generate the following code: // IFooEvents_SinkHelper SinkHelper = new IFooEvents_SinkHelper; il.Emit( OpCodes.Newobj, SinkHelperCons ); il.Emit( OpCodes.Stloc, ltSinkHelper ); // Generate the following code: // dwCookie = 0; il.Emit( OpCodes.Ldc_I4_0 ); il.Emit( OpCodes.Stloc, ltCookie ); // Generate the following code: // m_IFooEventsCP.Advise( SinkHelper, dwCookie ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Castclass, typeof(Object) ); il.Emit( OpCodes.Ldloca, ltCookie ); il.Emit( OpCodes.Callvirt, CPAdviseMethod ); // Generate the following code: // SinkHelper.m_dwCookie = dwCookie; il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Ldloc, ltCookie ); il.Emit( OpCodes.Stfld, CookieField ); // Generate the following code: // SinkHelper.m_FooDelegate = d; il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Ldarg, (short)1 ); il.Emit( OpCodes.Stfld, DelegateField ); // Generate the following code: // m_aIFooEventsHelpers.Add( SinkHelper ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Castclass, typeof(Object) ); il.Emit( OpCodes.Callvirt, ArrayListAddMethod ); il.Emit( OpCodes.Pop ); // Generate the following code: // } finally { il.BeginFinallyBlock(); // Generate the following code: // Monitor.Exit(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorExitMethod ); // Generate the following code: // } il.EndExceptionBlock(); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private MethodBuilder DefineRemoveEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo SrcItfMethod, Type SinkHelperClass, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP ) { Type[] aParamTypes; // Find the delegate on the event sink helper. FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" ); BCLDebug.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); BCLDebug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the ArrayList.RemoveAt method. aParamTypes = new Type[1]; aParamTypes[0] = typeof(Int32); MethodInfo ArrayListRemoveMethod = typeof(ArrayList).GetMethod( "RemoveAt", aParamTypes, null ); BCLDebug.Assert(ArrayListRemoveMethod != null, "Unable to find the method ArrayList.RemoveAt()"); // Retrieve the ArrayList.Item property get method. PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" ); BCLDebug.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod(); BCLDebug.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); // Retrieve the ArrayList.Count property get method. PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" ); BCLDebug.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod(); BCLDebug.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); // Retrieve the Delegate.Equals() method. aParamTypes[0] = typeof(Delegate); MethodInfo DelegateEqualsMethod = typeof(Delegate).GetMethod( "Equals", aParamTypes, null ); BCLDebug.Assert(DelegateEqualsMethod != null, "Unable to find the method Delegate.Equlals()"); // Retrieve the Monitor.Enter() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", aParamTypes, null ); BCLDebug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); BCLDebug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Retrieve the ConnectionPoint.Unadvise() method. MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" ); BCLDebug.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); // Retrieve the Marshal.ReleaseComObject() method. MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" ); BCLDebug.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); // Define the remove_XXX method. Type[] parameterTypes; parameterTypes = new Type[1]; parameterTypes[0] = DelegateField.FieldType; MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "remove_" + SrcItfMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, null, parameterTypes ); ILGenerator il = Meth.GetILGenerator(); // Declare the local variables. LocalBuilder ltNumSinkHelpers = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltSinkHelperCounter = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltCurrSinkHelper = il.DeclareLocal( SinkHelperClass ); // Generate the labels for the for loop. Label ForBeginLabel = il.DefineLabel(); Label ForEndLabel = il.DefineLabel(); Label FalseIfLabel = il.DefineLabel(); Label MonitorExitLabel = il.DefineLabel(); // Generate the following code: // Monitor.Enter(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorEnterMethod ); // Generate the following code: // try { il.BeginExceptionBlock(); // Generate the following code: // if ( m_aIFooEventsHelpers == null ) goto ForEndLabel; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Brfalse, ForEndLabel ); // Generate the following code: // int NumEventHelpers = m_aIFooEventsHelpers.Count; // int cEventHelpers = 0; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Callvirt, ArrayListSizeGetMethod ); il.Emit( OpCodes.Stloc, ltNumSinkHelpers ); il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( 0 >= NumEventHelpers ) goto ForEndLabel; il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Bge, ForEndLabel ); // Mark this as the beginning of the for loop's body. il.MarkLabel( ForBeginLabel ); // Generate the following code: // CurrentHelper = (IFooEvents_SinkHelper)m_aIFooEventsHelpers.Get( cEventHelpers ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Callvirt, ArrayListItemGetMethod ); il.Emit( OpCodes.Castclass, SinkHelperClass ); il.Emit( OpCodes.Stloc, ltCurrSinkHelper ); // Generate the following code: // if ( CurrentHelper.m_FooDelegate ) il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, DelegateField ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Beq, FalseIfLabel ); // Generate the following code: // if ( CurrentHelper.m_FooDelegate.Equals( d ) ) il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, DelegateField ); il.Emit( OpCodes.Ldarg, (short)1 ); il.Emit( OpCodes.Castclass, typeof(Object) ); il.Emit( OpCodes.Callvirt, DelegateEqualsMethod ); il.Emit( OpCodes.Ldc_I4, 0xff ); il.Emit( OpCodes.And ); il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Beq, FalseIfLabel ); // Generate the following code: // m_aIFooEventsHelpers.RemoveAt( cEventHelpers ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Callvirt, ArrayListRemoveMethod ); // Generate the following code: // m_IFooEventsCP.Unadvise( CurrentHelper.m_dwCookie ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, CookieField ); il.Emit( OpCodes.Callvirt, CPUnadviseMethod ); // Generate the following code: // if ( NumEventHelpers > 1) break; il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Ldc_I4, 1 ); il.Emit( OpCodes.Bgt, ForEndLabel ); // Generate the following code: // Marshal.ReleaseComObject(m_IFooEventsCP); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Call, ReleaseComObjectMethod ); il.Emit( OpCodes.Pop ); // Generate the following code: // m_IFooEventsCP = null; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Stfld, fbEventCP ); // Generate the following code: // m_aIFooEventsHelpers = null; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Stfld, fbSinkHelperArray ); // Generate the following code: // break; il.Emit( OpCodes.Br, ForEndLabel ); // Mark this as the label to jump to when the if statement is false. il.MarkLabel( FalseIfLabel ); // Generate the following code: // cEventHelpers++; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldc_I4, 1 ); il.Emit( OpCodes.Add ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( cEventHelpers < NumEventHelpers ) goto ForBeginLabel; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Blt, ForBeginLabel ); // Mark this as the end of the for loop's body. il.MarkLabel( ForEndLabel ); // Generate the following code: // } finally { il.BeginFinallyBlock(); // Generate the following code: // Monitor.Exit(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorExitMethod ); // Generate the following code: // } il.EndExceptionBlock(); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private MethodBuilder DefineInitSrcItfMethod( TypeBuilder OutputTypeBuilder, Type SourceInterface, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP, FieldBuilder fbCPC ) { // Retrieve the constructor info for the array list's default constructor. ConstructorInfo DefaultArrayListCons = typeof(ArrayList).GetConstructor(EventProviderWriter.DefaultLookup, null, new Type[0], null ); BCLDebug.Assert(DefaultArrayListCons != null, "Unable to find the constructor for class ArrayList"); // Temp byte array for Guid ubyte[] rgByteGuid = new ubyte[16]; // Retrieve the constructor info for the Guid constructor. Type[] aParamTypes = new Type[1]; aParamTypes[0] = typeof(Byte[]); ConstructorInfo ByteArrayGUIDCons = typeof(Guid).GetConstructor(EventProviderWriter.DefaultLookup, null, aParamTypes, null ); BCLDebug.Assert(ByteArrayGUIDCons != null, "Unable to find the constructor for GUID that accepts a string as argument"); // Retrieve the IConnectionPointContainer.FindConnectionPoint() method. MethodInfo CPCFindCPMethod = typeof(IConnectionPointContainer).GetMethod( "FindConnectionPoint" ); BCLDebug.Assert(CPCFindCPMethod != null, "Unable to find the method ConnectionPointContainer.FindConnectionPoint()"); // Define the Init method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Init", MethodAttributes.Private, null, null ); ILGenerator il = Meth.GetILGenerator(); // Declare the local variables. LocalBuilder ltCP = il.DeclareLocal( typeof(IConnectionPoint) ); LocalBuilder ltEvGuid = il.DeclareLocal( typeof(Guid) ); LocalBuilder ltByteArrayGuid = il.DeclareLocal( typeof(Byte[]) ); // Generate the following code: // IConnectionPoint CP = NULL; il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Stloc, ltCP ); // Get unsigned byte array for the GUID of the event interface. rgByteGuid = SourceInterface.GUID.ToByteArray(); // Generate the following code: // ubyte rgByteArray[] = new ubyte [16]; il.Emit( OpCodes.Ldc_I4, 0x10 ); il.Emit( OpCodes.Newarr, typeof(Byte) ); il.Emit( OpCodes.Stloc, ltByteArrayGuid ); // Generate the following code: // rgByteArray[i] = rgByteGuid[i]; for (int i = 0; i < 16; i++ ) { il.Emit( OpCodes.Ldloc, ltByteArrayGuid ); il.Emit( OpCodes.Ldc_I4, i ); il.Emit( OpCodes.Ldc_I4, (int) (rgByteGuid[i]) ); il.Emit( OpCodes.Stelem_I1); } // Generate the following code: // EventItfGuid = Guid( ubyte b[] ); il.Emit( OpCodes.Ldloca, ltEvGuid ); il.Emit( OpCodes.Ldloc, ltByteArrayGuid ); il.Emit( OpCodes.Call, ByteArrayGUIDCons ); // Generate the following code: // m_ConnectionPointContainer.FindConnectionPoint( EventItfGuid, CP ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbCPC ); il.Emit( OpCodes.Ldloca, ltEvGuid ); il.Emit( OpCodes.Ldloca, ltCP ); il.Emit( OpCodes.Callvirt, CPCFindCPMethod ); // Generate the following code: // m_ConnectionPoint = (IConnectionPoint)CP; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldloc, ltCP ); il.Emit( OpCodes.Castclass, typeof(IConnectionPoint) ); il.Emit( OpCodes.Stfld, fbEventCP ); // Generate the following code: // m_aEventSinkHelpers = new ArrayList; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Newobj, DefaultArrayListCons ); il.Emit( OpCodes.Stfld, fbSinkHelperArray ); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private void DefineConstructor( TypeBuilder OutputTypeBuilder, FieldBuilder fbCPC ) { // Retrieve the constructor info for the base class's constructor. ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null ); BCLDebug.Assert(DefaultBaseClsCons != null, "Unable to find the object's public default constructor"); // Define the default constructor. MethodAttributes ctorAttributes = MethodAttributes.SpecialName | (DefaultBaseClsCons.Attributes & MethodAttributes.MemberAccessMask); MethodBuilder Cons = OutputTypeBuilder.DefineMethod( ".ctor", ctorAttributes, null, new Type[]{typeof(Object)} ); ILGenerator il = Cons.GetILGenerator(); // Generate the call to the base class constructor. il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, DefaultBaseClsCons ); // Generate the following code: // m_ConnectionPointContainer = (IConnectionPointContainer)EventSource; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldarg, (short)1 ); il.Emit( OpCodes.Castclass, typeof(IConnectionPointContainer) ); il.Emit( OpCodes.Stfld, fbCPC ); // Generate the return opcode. il.Emit( OpCodes.Ret ); } private MethodBuilder DefineFinalizeMethod( TypeBuilder OutputTypeBuilder, Type SinkHelperClass, FieldBuilder fbSinkHelper, FieldBuilder fbEventCP ) { // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); BCLDebug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the ArrayList.Item property get method. PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" ); BCLDebug.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod(); BCLDebug.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); // Retrieve the ArrayList.Count property get method. PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" ); BCLDebug.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod(); BCLDebug.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); // Retrieve the ConnectionPoint.Unadvise() method. MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" ); BCLDebug.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); // Retrieve the Marshal.ReleaseComObject() method. MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" ); BCLDebug.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); // Retrieve the Monitor.Enter() method. Type[] aParamTypes = new Type[1]; aParamTypes[0] = typeof(Object); MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", aParamTypes, null ); BCLDebug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); BCLDebug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Define the Finalize method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Finalize", MethodAttributes.Public | MethodAttributes.Virtual, null, null ); ILGenerator il = Meth.GetILGenerator(); // Declare the local variables. LocalBuilder ltNumSinkHelpers = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltSinkHelperCounter = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltCurrSinkHelper = il.DeclareLocal( SinkHelperClass ); // Generate the following code: // Monitor.Enter(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorEnterMethod ); // Generate the following code: // try { il.BeginExceptionBlock(); // Generate the labels. Label ForBeginLabel = il.DefineLabel(); Label ReleaseComObjectLabel = il.DefineLabel(); Label AfterReleaseComObjectLabel = il.DefineLabel(); // Generate the following code: // if ( m_IFooEventsCP == null ) goto AfterReleaseComObjectLabel; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Brfalse, AfterReleaseComObjectLabel ); // Generate the following code: // int NumEventHelpers = m_aIFooEventsHelpers.Count; // int cEventHelpers = 0; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelper ); il.Emit( OpCodes.Callvirt, ArrayListSizeGetMethod ); il.Emit( OpCodes.Stloc, ltNumSinkHelpers ); il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( 0 >= NumEventHelpers ) goto ReleaseComObjectLabel; il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Bge, ReleaseComObjectLabel ); // Mark this as the beginning of the for loop's body. il.MarkLabel( ForBeginLabel ); // Generate the following code: // CurrentHelper = (IFooEvents_SinkHelper)m_aIFooEventsHelpers.Get( cEventHelpers ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelper ); il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Callvirt, ArrayListItemGetMethod ); il.Emit( OpCodes.Castclass, SinkHelperClass ); il.Emit( OpCodes.Stloc, ltCurrSinkHelper ); // Generate the following code: // m_IFooEventsCP.Unadvise( CurrentHelper.m_dwCookie ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, CookieField ); il.Emit( OpCodes.Callvirt, CPUnadviseMethod ); // Generate the following code: // cEventHelpers++; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldc_I4, 1 ); il.Emit( OpCodes.Add ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( cEventHelpers < NumEventHelpers ) goto ForBeginLabel; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Blt, ForBeginLabel ); // Mark this as the end of the for loop's body. il.MarkLabel( ReleaseComObjectLabel ); // Generate the following code: // Marshal.ReleaseComObject(m_IFooEventsCP); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Call, ReleaseComObjectMethod ); il.Emit( OpCodes.Pop ); // Mark this as the end of the for loop's body. il.MarkLabel( AfterReleaseComObjectLabel ); // Generate the following code: // } catch { il.BeginCatchBlock(typeof(System.Exception)); il.Emit( OpCodes.Pop ); // Generate the following code: // } finally { il.BeginFinallyBlock(); // Generate the following code: // Monitor.Exit(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorExitMethod ); // Generate the following code: // } il.EndExceptionBlock(); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private void DefineDisposeMethod( TypeBuilder OutputTypeBuilder, MethodBuilder FinalizeMethod ) { // Retrieve the method info for GC.SuppressFinalize(). MethodInfo SuppressFinalizeMethod = typeof(GC).GetMethod("SuppressFinalize"); BCLDebug.Assert(SuppressFinalizeMethod != null, "Unable to find the GC.SuppressFinalize"); // Define the Finalize method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Dispose", MethodAttributes.Public | MethodAttributes.Virtual, null, null ); ILGenerator il = Meth.GetILGenerator(); // Generate the following code: // Finalize() il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Callvirt, FinalizeMethod ); // Generate the following code: // GC.SuppressFinalize() il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, SuppressFinalizeMethod ); // Generate the return opcode. il.Emit( OpCodes.Ret ); } private ModuleBuilder m_OutputModule; private String m_strDestTypeName; private Type m_EventItfType; private Type m_SrcItfType; private Type m_SinkHelperType; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== namespace System.Runtime.InteropServices.TCEAdapterGen { using System.Runtime.InteropServices.ComTypes; using ubyte = System.Byte; using System; using System.Reflection; using System.Reflection.Emit; using System.Collections; using System.Threading; internal class EventProviderWriter { private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; public static readonly String GeneratedClassNamePostfix = ""; public EventProviderWriter( ModuleBuilder OutputModule, String strDestTypeName, Type EventItfType, Type SrcItfType, Type SinkHelperType ) { m_OutputModule = OutputModule; m_strDestTypeName = strDestTypeName; m_EventItfType = EventItfType; m_SrcItfType = SrcItfType; m_SinkHelperType = SinkHelperType; } public Type Perform() { // Create the event provider class. TypeBuilder OutputTypeBuilder = m_OutputModule.DefineType( m_strDestTypeName, TypeAttributes.Sealed | TypeAttributes.NotPublic, typeof(Object), new Type[]{m_EventItfType, typeof(IDisposable)} ); // Create the event source field. FieldBuilder fbCPC = OutputTypeBuilder.DefineField( "m_ConnectionPointContainer", typeof(IConnectionPointContainer), FieldAttributes.Private ); // Create array of event sink helpers. FieldBuilder fbSinkHelper = OutputTypeBuilder.DefineField( "m_aEventSinkHelpers", typeof(ArrayList), FieldAttributes.Private ); // Define the connection point field. FieldBuilder fbEventCP = OutputTypeBuilder.DefineField( "m_ConnectionPoint", typeof(IConnectionPoint), FieldAttributes.Private ); // Define the InitXXX method. MethodBuilder InitSrcItfMethodBuilder = DefineInitSrcItfMethod( OutputTypeBuilder, m_SrcItfType, fbSinkHelper, fbEventCP, fbCPC ); // Process all the methods in the event interface. MethodInfo[] aMethods = TCEAdapterGenerator.GetNonPropertyMethods(m_SrcItfType); for ( int cMethods = 0; cMethods < aMethods.Length; cMethods++ ) { if ( m_SrcItfType == aMethods[cMethods].DeclaringType ) { // Define the add_XXX method. MethodBuilder AddEventMethodBuilder = DefineAddEventMethod( OutputTypeBuilder, aMethods[cMethods], m_SinkHelperType, fbSinkHelper, fbEventCP, InitSrcItfMethodBuilder ); // Define the remove_XXX method. MethodBuilder RemoveEventMethodBuilder = DefineRemoveEventMethod( OutputTypeBuilder, aMethods[cMethods], m_SinkHelperType, fbSinkHelper, fbEventCP ); } } // Define the constructor. DefineConstructor( OutputTypeBuilder, fbCPC ); // Define the finalize method. MethodBuilder FinalizeMethod = DefineFinalizeMethod( OutputTypeBuilder, m_SinkHelperType, fbSinkHelper, fbEventCP ); // Define the Dispose method. DefineDisposeMethod( OutputTypeBuilder, FinalizeMethod); return OutputTypeBuilder.CreateType(); } private MethodBuilder DefineAddEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo SrcItfMethod, Type SinkHelperClass, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP, MethodBuilder mbInitSrcItf ) { Type[] aParamTypes; // Find the delegate on the event sink helper. FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" ); BCLDebug.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); BCLDebug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the sink helper's constructor. ConstructorInfo SinkHelperCons = SinkHelperClass.GetConstructor(EventProviderWriter.DefaultLookup | BindingFlags.NonPublic, null, new Type[0], null ); BCLDebug.Assert(SinkHelperCons != null, "Unable to find the constructor for the sink helper"); // Retrieve the IConnectionPoint.Advise method. MethodInfo CPAdviseMethod = typeof(IConnectionPoint).GetMethod( "Advise" ); BCLDebug.Assert(CPAdviseMethod != null, "Unable to find the method ConnectionPoint.Advise"); // Retrieve the ArrayList.Add method. aParamTypes = new Type[1]; aParamTypes[0] = typeof(Object); MethodInfo ArrayListAddMethod = typeof(ArrayList).GetMethod( "Add", aParamTypes, null ); BCLDebug.Assert(ArrayListAddMethod != null, "Unable to find the method ArrayList.Add"); // Retrieve the Monitor.Enter() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", aParamTypes, null ); BCLDebug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); BCLDebug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Define the add_XXX method. Type[] parameterTypes; parameterTypes = new Type[1]; parameterTypes[0] = DelegateField.FieldType; MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "add_" + SrcItfMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, null, parameterTypes ); ILGenerator il = Meth.GetILGenerator(); // Define a label for the m_IFooEventsCP comparision. Label EventCPNonNullLabel = il.DefineLabel(); // Declare the local variables. LocalBuilder ltSinkHelper = il.DeclareLocal( SinkHelperClass ); LocalBuilder ltCookie = il.DeclareLocal( typeof(Int32) ); // Generate the following code: // Monitor.Enter(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorEnterMethod ); // Generate the following code: // try { il.BeginExceptionBlock(); // Generate the following code: // if ( m_IFooEventsCP != null ) goto EventCPNonNullLabel; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Brtrue, EventCPNonNullLabel ); // Generate the following code: // InitIFooEvents(); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, mbInitSrcItf ); // Mark this as label to jump to if the CP is not null. il.MarkLabel( EventCPNonNullLabel ); // Generate the following code: // IFooEvents_SinkHelper SinkHelper = new IFooEvents_SinkHelper; il.Emit( OpCodes.Newobj, SinkHelperCons ); il.Emit( OpCodes.Stloc, ltSinkHelper ); // Generate the following code: // dwCookie = 0; il.Emit( OpCodes.Ldc_I4_0 ); il.Emit( OpCodes.Stloc, ltCookie ); // Generate the following code: // m_IFooEventsCP.Advise( SinkHelper, dwCookie ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Castclass, typeof(Object) ); il.Emit( OpCodes.Ldloca, ltCookie ); il.Emit( OpCodes.Callvirt, CPAdviseMethod ); // Generate the following code: // SinkHelper.m_dwCookie = dwCookie; il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Ldloc, ltCookie ); il.Emit( OpCodes.Stfld, CookieField ); // Generate the following code: // SinkHelper.m_FooDelegate = d; il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Ldarg, (short)1 ); il.Emit( OpCodes.Stfld, DelegateField ); // Generate the following code: // m_aIFooEventsHelpers.Add( SinkHelper ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Ldloc, ltSinkHelper ); il.Emit( OpCodes.Castclass, typeof(Object) ); il.Emit( OpCodes.Callvirt, ArrayListAddMethod ); il.Emit( OpCodes.Pop ); // Generate the following code: // } finally { il.BeginFinallyBlock(); // Generate the following code: // Monitor.Exit(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorExitMethod ); // Generate the following code: // } il.EndExceptionBlock(); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private MethodBuilder DefineRemoveEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo SrcItfMethod, Type SinkHelperClass, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP ) { Type[] aParamTypes; // Find the delegate on the event sink helper. FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" ); BCLDebug.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper"); // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); BCLDebug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the ArrayList.RemoveAt method. aParamTypes = new Type[1]; aParamTypes[0] = typeof(Int32); MethodInfo ArrayListRemoveMethod = typeof(ArrayList).GetMethod( "RemoveAt", aParamTypes, null ); BCLDebug.Assert(ArrayListRemoveMethod != null, "Unable to find the method ArrayList.RemoveAt()"); // Retrieve the ArrayList.Item property get method. PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" ); BCLDebug.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod(); BCLDebug.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); // Retrieve the ArrayList.Count property get method. PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" ); BCLDebug.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod(); BCLDebug.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); // Retrieve the Delegate.Equals() method. aParamTypes[0] = typeof(Delegate); MethodInfo DelegateEqualsMethod = typeof(Delegate).GetMethod( "Equals", aParamTypes, null ); BCLDebug.Assert(DelegateEqualsMethod != null, "Unable to find the method Delegate.Equlals()"); // Retrieve the Monitor.Enter() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", aParamTypes, null ); BCLDebug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); BCLDebug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Retrieve the ConnectionPoint.Unadvise() method. MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" ); BCLDebug.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); // Retrieve the Marshal.ReleaseComObject() method. MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" ); BCLDebug.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); // Define the remove_XXX method. Type[] parameterTypes; parameterTypes = new Type[1]; parameterTypes[0] = DelegateField.FieldType; MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "remove_" + SrcItfMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, null, parameterTypes ); ILGenerator il = Meth.GetILGenerator(); // Declare the local variables. LocalBuilder ltNumSinkHelpers = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltSinkHelperCounter = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltCurrSinkHelper = il.DeclareLocal( SinkHelperClass ); // Generate the labels for the for loop. Label ForBeginLabel = il.DefineLabel(); Label ForEndLabel = il.DefineLabel(); Label FalseIfLabel = il.DefineLabel(); Label MonitorExitLabel = il.DefineLabel(); // Generate the following code: // Monitor.Enter(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorEnterMethod ); // Generate the following code: // try { il.BeginExceptionBlock(); // Generate the following code: // if ( m_aIFooEventsHelpers == null ) goto ForEndLabel; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Brfalse, ForEndLabel ); // Generate the following code: // int NumEventHelpers = m_aIFooEventsHelpers.Count; // int cEventHelpers = 0; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Callvirt, ArrayListSizeGetMethod ); il.Emit( OpCodes.Stloc, ltNumSinkHelpers ); il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( 0 >= NumEventHelpers ) goto ForEndLabel; il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Bge, ForEndLabel ); // Mark this as the beginning of the for loop's body. il.MarkLabel( ForBeginLabel ); // Generate the following code: // CurrentHelper = (IFooEvents_SinkHelper)m_aIFooEventsHelpers.Get( cEventHelpers ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Callvirt, ArrayListItemGetMethod ); il.Emit( OpCodes.Castclass, SinkHelperClass ); il.Emit( OpCodes.Stloc, ltCurrSinkHelper ); // Generate the following code: // if ( CurrentHelper.m_FooDelegate ) il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, DelegateField ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Beq, FalseIfLabel ); // Generate the following code: // if ( CurrentHelper.m_FooDelegate.Equals( d ) ) il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, DelegateField ); il.Emit( OpCodes.Ldarg, (short)1 ); il.Emit( OpCodes.Castclass, typeof(Object) ); il.Emit( OpCodes.Callvirt, DelegateEqualsMethod ); il.Emit( OpCodes.Ldc_I4, 0xff ); il.Emit( OpCodes.And ); il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Beq, FalseIfLabel ); // Generate the following code: // m_aIFooEventsHelpers.RemoveAt( cEventHelpers ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelperArray ); il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Callvirt, ArrayListRemoveMethod ); // Generate the following code: // m_IFooEventsCP.Unadvise( CurrentHelper.m_dwCookie ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, CookieField ); il.Emit( OpCodes.Callvirt, CPUnadviseMethod ); // Generate the following code: // if ( NumEventHelpers > 1) break; il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Ldc_I4, 1 ); il.Emit( OpCodes.Bgt, ForEndLabel ); // Generate the following code: // Marshal.ReleaseComObject(m_IFooEventsCP); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Call, ReleaseComObjectMethod ); il.Emit( OpCodes.Pop ); // Generate the following code: // m_IFooEventsCP = null; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Stfld, fbEventCP ); // Generate the following code: // m_aIFooEventsHelpers = null; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Stfld, fbSinkHelperArray ); // Generate the following code: // break; il.Emit( OpCodes.Br, ForEndLabel ); // Mark this as the label to jump to when the if statement is false. il.MarkLabel( FalseIfLabel ); // Generate the following code: // cEventHelpers++; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldc_I4, 1 ); il.Emit( OpCodes.Add ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( cEventHelpers < NumEventHelpers ) goto ForBeginLabel; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Blt, ForBeginLabel ); // Mark this as the end of the for loop's body. il.MarkLabel( ForEndLabel ); // Generate the following code: // } finally { il.BeginFinallyBlock(); // Generate the following code: // Monitor.Exit(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorExitMethod ); // Generate the following code: // } il.EndExceptionBlock(); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private MethodBuilder DefineInitSrcItfMethod( TypeBuilder OutputTypeBuilder, Type SourceInterface, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP, FieldBuilder fbCPC ) { // Retrieve the constructor info for the array list's default constructor. ConstructorInfo DefaultArrayListCons = typeof(ArrayList).GetConstructor(EventProviderWriter.DefaultLookup, null, new Type[0], null ); BCLDebug.Assert(DefaultArrayListCons != null, "Unable to find the constructor for class ArrayList"); // Temp byte array for Guid ubyte[] rgByteGuid = new ubyte[16]; // Retrieve the constructor info for the Guid constructor. Type[] aParamTypes = new Type[1]; aParamTypes[0] = typeof(Byte[]); ConstructorInfo ByteArrayGUIDCons = typeof(Guid).GetConstructor(EventProviderWriter.DefaultLookup, null, aParamTypes, null ); BCLDebug.Assert(ByteArrayGUIDCons != null, "Unable to find the constructor for GUID that accepts a string as argument"); // Retrieve the IConnectionPointContainer.FindConnectionPoint() method. MethodInfo CPCFindCPMethod = typeof(IConnectionPointContainer).GetMethod( "FindConnectionPoint" ); BCLDebug.Assert(CPCFindCPMethod != null, "Unable to find the method ConnectionPointContainer.FindConnectionPoint()"); // Define the Init method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Init", MethodAttributes.Private, null, null ); ILGenerator il = Meth.GetILGenerator(); // Declare the local variables. LocalBuilder ltCP = il.DeclareLocal( typeof(IConnectionPoint) ); LocalBuilder ltEvGuid = il.DeclareLocal( typeof(Guid) ); LocalBuilder ltByteArrayGuid = il.DeclareLocal( typeof(Byte[]) ); // Generate the following code: // IConnectionPoint CP = NULL; il.Emit( OpCodes.Ldnull ); il.Emit( OpCodes.Stloc, ltCP ); // Get unsigned byte array for the GUID of the event interface. rgByteGuid = SourceInterface.GUID.ToByteArray(); // Generate the following code: // ubyte rgByteArray[] = new ubyte [16]; il.Emit( OpCodes.Ldc_I4, 0x10 ); il.Emit( OpCodes.Newarr, typeof(Byte) ); il.Emit( OpCodes.Stloc, ltByteArrayGuid ); // Generate the following code: // rgByteArray[i] = rgByteGuid[i]; for (int i = 0; i < 16; i++ ) { il.Emit( OpCodes.Ldloc, ltByteArrayGuid ); il.Emit( OpCodes.Ldc_I4, i ); il.Emit( OpCodes.Ldc_I4, (int) (rgByteGuid[i]) ); il.Emit( OpCodes.Stelem_I1); } // Generate the following code: // EventItfGuid = Guid( ubyte b[] ); il.Emit( OpCodes.Ldloca, ltEvGuid ); il.Emit( OpCodes.Ldloc, ltByteArrayGuid ); il.Emit( OpCodes.Call, ByteArrayGUIDCons ); // Generate the following code: // m_ConnectionPointContainer.FindConnectionPoint( EventItfGuid, CP ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbCPC ); il.Emit( OpCodes.Ldloca, ltEvGuid ); il.Emit( OpCodes.Ldloca, ltCP ); il.Emit( OpCodes.Callvirt, CPCFindCPMethod ); // Generate the following code: // m_ConnectionPoint = (IConnectionPoint)CP; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldloc, ltCP ); il.Emit( OpCodes.Castclass, typeof(IConnectionPoint) ); il.Emit( OpCodes.Stfld, fbEventCP ); // Generate the following code: // m_aEventSinkHelpers = new ArrayList; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Newobj, DefaultArrayListCons ); il.Emit( OpCodes.Stfld, fbSinkHelperArray ); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private void DefineConstructor( TypeBuilder OutputTypeBuilder, FieldBuilder fbCPC ) { // Retrieve the constructor info for the base class's constructor. ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null ); BCLDebug.Assert(DefaultBaseClsCons != null, "Unable to find the object's public default constructor"); // Define the default constructor. MethodAttributes ctorAttributes = MethodAttributes.SpecialName | (DefaultBaseClsCons.Attributes & MethodAttributes.MemberAccessMask); MethodBuilder Cons = OutputTypeBuilder.DefineMethod( ".ctor", ctorAttributes, null, new Type[]{typeof(Object)} ); ILGenerator il = Cons.GetILGenerator(); // Generate the call to the base class constructor. il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, DefaultBaseClsCons ); // Generate the following code: // m_ConnectionPointContainer = (IConnectionPointContainer)EventSource; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldarg, (short)1 ); il.Emit( OpCodes.Castclass, typeof(IConnectionPointContainer) ); il.Emit( OpCodes.Stfld, fbCPC ); // Generate the return opcode. il.Emit( OpCodes.Ret ); } private MethodBuilder DefineFinalizeMethod( TypeBuilder OutputTypeBuilder, Type SinkHelperClass, FieldBuilder fbSinkHelper, FieldBuilder fbEventCP ) { // Find the cookie on the event sink helper. FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" ); BCLDebug.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper"); // Retrieve the ArrayList.Item property get method. PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" ); BCLDebug.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item"); MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod(); BCLDebug.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item"); // Retrieve the ArrayList.Count property get method. PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" ); BCLDebug.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count"); MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod(); BCLDebug.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count"); // Retrieve the ConnectionPoint.Unadvise() method. MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" ); BCLDebug.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()"); // Retrieve the Marshal.ReleaseComObject() method. MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" ); BCLDebug.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()"); // Retrieve the Monitor.Enter() method. Type[] aParamTypes = new Type[1]; aParamTypes[0] = typeof(Object); MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", aParamTypes, null ); BCLDebug.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()"); // Retrieve the Monitor.Exit() method. aParamTypes[0] = typeof(Object); MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null ); BCLDebug.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()"); // Define the Finalize method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Finalize", MethodAttributes.Public | MethodAttributes.Virtual, null, null ); ILGenerator il = Meth.GetILGenerator(); // Declare the local variables. LocalBuilder ltNumSinkHelpers = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltSinkHelperCounter = il.DeclareLocal( typeof(Int32) ); LocalBuilder ltCurrSinkHelper = il.DeclareLocal( SinkHelperClass ); // Generate the following code: // Monitor.Enter(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorEnterMethod ); // Generate the following code: // try { il.BeginExceptionBlock(); // Generate the labels. Label ForBeginLabel = il.DefineLabel(); Label ReleaseComObjectLabel = il.DefineLabel(); Label AfterReleaseComObjectLabel = il.DefineLabel(); // Generate the following code: // if ( m_IFooEventsCP == null ) goto AfterReleaseComObjectLabel; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Brfalse, AfterReleaseComObjectLabel ); // Generate the following code: // int NumEventHelpers = m_aIFooEventsHelpers.Count; // int cEventHelpers = 0; il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelper ); il.Emit( OpCodes.Callvirt, ArrayListSizeGetMethod ); il.Emit( OpCodes.Stloc, ltNumSinkHelpers ); il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( 0 >= NumEventHelpers ) goto ReleaseComObjectLabel; il.Emit( OpCodes.Ldc_I4, 0 ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Bge, ReleaseComObjectLabel ); // Mark this as the beginning of the for loop's body. il.MarkLabel( ForBeginLabel ); // Generate the following code: // CurrentHelper = (IFooEvents_SinkHelper)m_aIFooEventsHelpers.Get( cEventHelpers ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbSinkHelper ); il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Callvirt, ArrayListItemGetMethod ); il.Emit( OpCodes.Castclass, SinkHelperClass ); il.Emit( OpCodes.Stloc, ltCurrSinkHelper ); // Generate the following code: // m_IFooEventsCP.Unadvise( CurrentHelper.m_dwCookie ); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Ldloc, ltCurrSinkHelper ); il.Emit( OpCodes.Ldfld, CookieField ); il.Emit( OpCodes.Callvirt, CPUnadviseMethod ); // Generate the following code: // cEventHelpers++; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldc_I4, 1 ); il.Emit( OpCodes.Add ); il.Emit( OpCodes.Stloc, ltSinkHelperCounter ); // Generate the following code: // if ( cEventHelpers < NumEventHelpers ) goto ForBeginLabel; il.Emit( OpCodes.Ldloc, ltSinkHelperCounter ); il.Emit( OpCodes.Ldloc, ltNumSinkHelpers ); il.Emit( OpCodes.Blt, ForBeginLabel ); // Mark this as the end of the for loop's body. il.MarkLabel( ReleaseComObjectLabel ); // Generate the following code: // Marshal.ReleaseComObject(m_IFooEventsCP); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Ldfld, fbEventCP ); il.Emit( OpCodes.Call, ReleaseComObjectMethod ); il.Emit( OpCodes.Pop ); // Mark this as the end of the for loop's body. il.MarkLabel( AfterReleaseComObjectLabel ); // Generate the following code: // } catch { il.BeginCatchBlock(typeof(System.Exception)); il.Emit( OpCodes.Pop ); // Generate the following code: // } finally { il.BeginFinallyBlock(); // Generate the following code: // Monitor.Exit(this); il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, MonitorExitMethod ); // Generate the following code: // } il.EndExceptionBlock(); // Generate the return opcode. il.Emit( OpCodes.Ret ); return Meth; } private void DefineDisposeMethod( TypeBuilder OutputTypeBuilder, MethodBuilder FinalizeMethod ) { // Retrieve the method info for GC.SuppressFinalize(). MethodInfo SuppressFinalizeMethod = typeof(GC).GetMethod("SuppressFinalize"); BCLDebug.Assert(SuppressFinalizeMethod != null, "Unable to find the GC.SuppressFinalize"); // Define the Finalize method itself. MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Dispose", MethodAttributes.Public | MethodAttributes.Virtual, null, null ); ILGenerator il = Meth.GetILGenerator(); // Generate the following code: // Finalize() il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Callvirt, FinalizeMethod ); // Generate the following code: // GC.SuppressFinalize() il.Emit( OpCodes.Ldarg, (short)0 ); il.Emit( OpCodes.Call, SuppressFinalizeMethod ); // Generate the return opcode. il.Emit( OpCodes.Ret ); } private ModuleBuilder m_OutputModule; private String m_strDestTypeName; private Type m_EventItfType; private Type m_SrcItfType; private Type m_SinkHelperType; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Rotation3DKeyFrameCollection.cs
- ModelServiceImpl.cs
- Mapping.cs
- NativeMethods.cs
- TableRow.cs
- DockPanel.cs
- CompilerInfo.cs
- ForeignKeyConstraint.cs
- SwitchElementsCollection.cs
- SimpleMailWebEventProvider.cs
- Parameter.cs
- ListViewDeleteEventArgs.cs
- XsltQilFactory.cs
- AspNetHostingPermission.cs
- DataBindingHandlerAttribute.cs
- ExpressionNode.cs
- UnmanagedMemoryStreamWrapper.cs
- MessageQueueEnumerator.cs
- ProjectionPathBuilder.cs
- RawStylusSystemGestureInputReport.cs
- MappingSource.cs
- LoadedOrUnloadedOperation.cs
- filewebresponse.cs
- WebConfigurationHostFileChange.cs
- PolyQuadraticBezierSegment.cs
- FileDialog_Vista.cs
- SafeEventLogReadHandle.cs
- TextEditorDragDrop.cs
- ResourceCodeDomSerializer.cs
- SiteMapHierarchicalDataSourceView.cs
- InkCanvas.cs
- DigitalSignature.cs
- QilList.cs
- Compiler.cs
- TimeIntervalCollection.cs
- NativeMethodsOther.cs
- SHA256Managed.cs
- SamlDoNotCacheCondition.cs
- ConfigXmlReader.cs
- ValidationError.cs
- ToolStripItem.cs
- PackWebResponse.cs
- RenderDataDrawingContext.cs
- ScrollableControl.cs
- validation.cs
- RegexCaptureCollection.cs
- CalendarAutomationPeer.cs
- SoapReflectionImporter.cs
- IDictionary.cs
- EarlyBoundInfo.cs
- PermissionAttributes.cs
- mactripleDES.cs
- ProcessHost.cs
- CategoryGridEntry.cs
- SoapBinding.cs
- MultiTrigger.cs
- DbQueryCommandTree.cs
- followingsibling.cs
- TreeBuilderXamlTranslator.cs
- GCHandleCookieTable.cs
- CollectionContainer.cs
- DerivedKeyCachingSecurityTokenSerializer.cs
- ButtonBaseAutomationPeer.cs
- MemberCollection.cs
- XmlTextWriter.cs
- ComponentCommands.cs
- MetafileHeader.cs
- SqlDataSourceCustomCommandEditor.cs
- StylusPoint.cs
- DBPropSet.cs
- Converter.cs
- UpdateEventArgs.cs
- SecurityTokenSerializer.cs
- CancelEventArgs.cs
- Config.cs
- CompositeTypefaceMetrics.cs
- HttpModuleCollection.cs
- HttpWriter.cs
- ListSortDescription.cs
- ListControlStringCollectionEditor.cs
- RemotingServices.cs
- BindingsCollection.cs
- SimpleColumnProvider.cs
- TextSchema.cs
- AccessViolationException.cs
- DetailsViewAutoFormat.cs
- Vector3DIndependentAnimationStorage.cs
- ServiceNameCollection.cs
- ItemContainerPattern.cs
- ValidatingReaderNodeData.cs
- Window.cs
- MonthCalendar.cs
- RuleCache.cs
- StructuredTypeInfo.cs
- AccessibleObject.cs
- CodeIterationStatement.cs
- ToolStripItemEventArgs.cs
- SecurityTokenProviderContainer.cs
- XmlHierarchyData.cs
- RegexMatch.cs