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
- DataGridViewElement.cs
- RowToParametersTransformer.cs
- InvalidProgramException.cs
- SystemEvents.cs
- SchemaNamespaceManager.cs
- FileAuthorizationModule.cs
- VoiceChangeEventArgs.cs
- DbConnectionPoolGroupProviderInfo.cs
- PartialToken.cs
- log.cs
- DisplayInformation.cs
- ExpressionBinding.cs
- GcSettings.cs
- StrongNamePublicKeyBlob.cs
- ScriptHandlerFactory.cs
- VirtualDirectoryMappingCollection.cs
- TypePresenter.xaml.cs
- TypedElement.cs
- WebPartDisplayModeCollection.cs
- CellLabel.cs
- CapiHashAlgorithm.cs
- SourceItem.cs
- DirectoryNotFoundException.cs
- XmlDataFileEditor.cs
- XmlCDATASection.cs
- ExpandoClass.cs
- ExceptionCollection.cs
- CompositeActivityTypeDescriptorProvider.cs
- HttpDebugHandler.cs
- InstanceNotFoundException.cs
- Compiler.cs
- LoadItemsEventArgs.cs
- StateChangeEvent.cs
- Int32AnimationBase.cs
- ResourcePermissionBase.cs
- DataControlCommands.cs
- ArraySegment.cs
- ComboBoxAutomationPeer.cs
- CommonRemoteMemoryBlock.cs
- FocusWithinProperty.cs
- SafeTimerHandle.cs
- AssertFilter.cs
- Decimal.cs
- DTCTransactionManager.cs
- PhysicalFontFamily.cs
- MemberAssignmentAnalysis.cs
- SimpleRecyclingCache.cs
- Substitution.cs
- HtmlSelect.cs
- Wildcard.cs
- DesignerImageAdapter.cs
- PageCache.cs
- NativeMethods.cs
- WindowInteractionStateTracker.cs
- QueryConverter.cs
- OleDbFactory.cs
- XPathParser.cs
- ProviderConnectionPointCollection.cs
- ScriptingSectionGroup.cs
- UnsafeNativeMethodsPenimc.cs
- ReflectTypeDescriptionProvider.cs
- PasswordPropertyTextAttribute.cs
- LambdaCompiler.Expressions.cs
- HttpResponseHeader.cs
- CreateInstanceBinder.cs
- StyleTypedPropertyAttribute.cs
- FixedFindEngine.cs
- LeftCellWrapper.cs
- FlowDocumentPage.cs
- StoryFragments.cs
- CommandLibraryHelper.cs
- RadioButton.cs
- SmiContextFactory.cs
- ConfigXmlWhitespace.cs
- BCLDebug.cs
- SafeRightsManagementSessionHandle.cs
- ConvertEvent.cs
- SqlUserDefinedAggregateAttribute.cs
- CodeParameterDeclarationExpression.cs
- CompilerState.cs
- DetailsView.cs
- String.cs
- TreeViewEvent.cs
- httpserverutility.cs
- ObjectParameter.cs
- AddInSegmentDirectoryNotFoundException.cs
- MenuEventArgs.cs
- ServiceAuthorizationManager.cs
- AttachedPropertyBrowsableForChildrenAttribute.cs
- ErrorTableItemStyle.cs
- SortedList.cs
- RangeValueProviderWrapper.cs
- StringConverter.cs
- RelationshipEntry.cs
- PolicyStatement.cs
- RoleGroup.cs
- CLRBindingWorker.cs
- ValueUnavailableException.cs
- XmlJsonWriter.cs
- TextSpanModifier.cs