Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / InteropServices / TCEAdapterGen / EventSinkHelperWriter.cs / 1 / EventSinkHelperWriter.cs
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
namespace System.Runtime.InteropServices.TCEAdapterGen {
using System.Runtime.InteropServices;
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections;
internal class EventSinkHelperWriter
{
public static readonly String GeneratedTypeNamePostfix = "_SinkHelper";
public EventSinkHelperWriter( ModuleBuilder OutputModule, Type InputType, Type EventItfType )
{
m_InputType = InputType;
m_OutputModule = OutputModule;
m_EventItfType = EventItfType;
}
public Type Perform()
{
// Create the output Type.
Type[] aInterfaces = new Type[1];
aInterfaces[0] = m_InputType;
String strFullName = null;
String strNameSpace = NameSpaceExtractor.ExtractNameSpace( m_EventItfType.FullName );
if (strNameSpace != "")
strFullName = strNameSpace + ".";
strFullName += m_InputType.Name + GeneratedTypeNamePostfix;
TypeBuilder OutputTypeBuilder = TCEAdapterGenerator.DefineUniqueType(
strFullName,
TypeAttributes.Sealed | TypeAttributes.Public,
null,
aInterfaces,
m_OutputModule
);
// Hide the _SinkProvider interface
TCEAdapterGenerator.SetHiddenAttribute(OutputTypeBuilder);
// Set the class interface to none.
TCEAdapterGenerator.SetClassInterfaceTypeToNone(OutputTypeBuilder);
// Retrieve the property methods on the input interface and give them a dummy implementation.
MethodInfo[] pMethods = TCEAdapterGenerator.GetPropertyMethods(m_InputType);
foreach (MethodInfo method in pMethods)
{
DefineBlankMethod(OutputTypeBuilder, method);
}
// Retrieve the non-property methods on the input interface.
MethodInfo[] aMethods = TCEAdapterGenerator.GetNonPropertyMethods(m_InputType);
// Allocate an array to contain the delegate fields.
FieldBuilder[] afbDelegates = new FieldBuilder[aMethods.Length];
// Process all the methods on the input interface.
for ( int cMethods = 0; cMethods < aMethods.Length; cMethods++ )
{
if ( m_InputType == aMethods[cMethods].DeclaringType )
{
// Retrieve the delegate type from the add_XXX method.
MethodInfo AddMeth = m_EventItfType.GetMethod( "add_" + aMethods[cMethods].Name );
ParameterInfo[] aParams = AddMeth.GetParameters();
BCLDebug.Assert(aParams.Length == 1, "All event interface methods must take a single delegate derived type and have a void return type");
Type DelegateCls = aParams[0].ParameterType;
// Define the delegate instance field.
afbDelegates[cMethods] = OutputTypeBuilder.DefineField(
"m_" + aMethods[cMethods].Name + "Delegate",
DelegateCls,
FieldAttributes.Public
);
// Define the event method itself.
DefineEventMethod( OutputTypeBuilder, aMethods[cMethods], DelegateCls, afbDelegates[cMethods] );
}
}
// Create the cookie field.
FieldBuilder fbCookie = OutputTypeBuilder.DefineField(
"m_dwCookie",
typeof(Int32),
FieldAttributes.Public
);
// Define the constructor.
DefineConstructor( OutputTypeBuilder, fbCookie, afbDelegates );
return OutputTypeBuilder.CreateType();
}
private void DefineBlankMethod(TypeBuilder OutputTypeBuilder, MethodInfo Method)
{
ParameterInfo[] PIs = Method.GetParameters();
Type[] parameters = new Type[PIs.Length];
for (int i=0; i < PIs.Length; i++)
{
parameters[i] = PIs[i].ParameterType;
}
MethodBuilder Meth = OutputTypeBuilder.DefineMethod(Method.Name,
Method.Attributes & ~MethodAttributes.Abstract,
Method.CallingConvention,
Method.ReturnType,
parameters);
ILGenerator il = Meth.GetILGenerator();
AddReturn(Method.ReturnType, il, Meth);
il.Emit(OpCodes.Ret);
}
private void DefineEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo Method, Type DelegateCls, FieldBuilder fbDelegate )
{
// Retrieve the method info for the invoke method on the delegate.
MethodInfo DelegateInvokeMethod = DelegateCls.GetMethod( "Invoke" );
BCLDebug.Assert(DelegateInvokeMethod != null, "Unable to find method Delegate.Invoke()");
// Retrieve the return type.
Type ReturnType = Method.ReturnType;
// Define the actual event method.
ParameterInfo[] paramInfos = Method.GetParameters();
Type[] parameterTypes;
if (paramInfos != null)
{
parameterTypes = new Type[paramInfos.Length];
for (int i = 0; i < paramInfos.Length; i++)
{
parameterTypes[i] = paramInfos[i].ParameterType;
}
}
else
parameterTypes = null;
MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Virtual;
MethodBuilder Meth = OutputTypeBuilder.DefineMethod( Method.Name,
attr,
CallingConventions.Standard,
ReturnType,
parameterTypes);
// We explicitly do not specify parameter name and attributes since this Type
// is not meant to be exposed to the user. It is only used internally to do the
// connection point to TCE mapping.
ILGenerator il = Meth.GetILGenerator();
// Create the exit branch.
Label ExitLabel = il.DefineLabel();
// Generate the code that verifies that the delegate is not null.
il.Emit( OpCodes.Ldarg, (short)0 );
il.Emit( OpCodes.Ldfld, fbDelegate );
il.Emit( OpCodes.Brfalse, ExitLabel );
// The delegate is not NULL so we need to invoke it.
il.Emit( OpCodes.Ldarg, (short)0 );
il.Emit( OpCodes.Ldfld, fbDelegate );
// Generate the code to load the arguments before we call invoke.
ParameterInfo[] aParams = Method.GetParameters();
for ( int cParams = 0; cParams < aParams.Length; cParams++ )
{
il.Emit( OpCodes.Ldarg, (short)(cParams + 1) );
}
// Generate a tail call to invoke. This will cause the callvirt to return
// directly to the caller of the current method instead of actually coming
// back to the current method and returning. This will cause the value returned
// from the call to the COM server to be returned to the caller of this method.
il.Emit( OpCodes.Callvirt, DelegateInvokeMethod );
il.Emit( OpCodes.Ret );
// This is the label that will be jumped to if no delegate is present.
il.MarkLabel( ExitLabel );
AddReturn(ReturnType, il, Meth);
il.Emit( OpCodes.Ret );
}
private void AddReturn(Type ReturnType, ILGenerator il, MethodBuilder Meth)
{
// Place a dummy return value on the stack before we return.
if ( ReturnType == typeof(void) )
{
// There is nothing to place on the stack.
}
else if ( ReturnType.IsPrimitive )
{
switch (System.Type.GetTypeCode(ReturnType))
{
case TypeCode.Boolean:
case TypeCode.Char:
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
il.Emit( OpCodes.Ldc_I4_0 );
break;
case TypeCode.Int64:
case TypeCode.UInt64:
il.Emit( OpCodes.Ldc_I4_0 );
il.Emit( OpCodes.Conv_I8 );
break;
case TypeCode.Single:
il.Emit( OpCodes.Ldc_R4, 0 );
break;
case TypeCode.Double:
il.Emit( OpCodes.Ldc_R4, 0 );
il.Emit( OpCodes.Conv_R8 );
break;
default:
// "TypeCode" does not include IntPtr, so special case it.
if ( ReturnType == typeof(IntPtr) )
il.Emit( OpCodes.Ldc_I4_0 );
else
BCLDebug.Assert(false, "Unexpected type for Primitive type.");
break;
}
}
else if ( ReturnType.IsValueType )
{
// Allocate stack space for the return value type. Zero-init.
Meth.InitLocals = true;
LocalBuilder ltRetVal = il.DeclareLocal( ReturnType );
// Load the value class on the stack.
il.Emit( OpCodes.Ldloc_S, ltRetVal );
}
else
{
// The return type is a normal type.
il.Emit( OpCodes.Ldnull );
}
}
private void DefineConstructor( TypeBuilder OutputTypeBuilder, FieldBuilder fbCookie, FieldBuilder[] afbDelegates )
{
// Retrieve the constructor info for the base classe's constructor.
ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, new Type[0], null );
BCLDebug.Assert(DefaultBaseClsCons != null, "Unable to find the constructor for class " + m_InputType.Name);
// Define the default constructor.
MethodBuilder Cons = OutputTypeBuilder.DefineMethod( ".ctor",
MethodAttributes.Assembly | MethodAttributes.SpecialName,
CallingConventions.Standard,
null,
null);
ILGenerator il = Cons.GetILGenerator();
// Generate the code to call the constructor of the base class.
il.Emit( OpCodes.Ldarg, (short)0 );
il.Emit( OpCodes.Call, DefaultBaseClsCons );
// Generate the code to set the cookie field to 0.
il.Emit( OpCodes.Ldarg, (short)0 );
il.Emit( OpCodes.Ldc_I4, 0 );
il.Emit( OpCodes.Stfld, fbCookie );
// Generate the code to set all the delegates to NULL.
for ( int cDelegates = 0; cDelegates < afbDelegates.Length; cDelegates++ )
{
if (afbDelegates[cDelegates] != null)
{
il.Emit( OpCodes.Ldarg,(short)0 );
il.Emit( OpCodes.Ldnull );
il.Emit( OpCodes.Stfld, afbDelegates[cDelegates] );
}
}
// Emit the return opcode.
il.Emit( OpCodes.Ret );
}
private Type m_InputType;
private Type m_EventItfType;
private ModuleBuilder m_OutputModule;
}
}
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ColumnTypeConverter.cs
- ContactManager.cs
- XmlSchemaAttributeGroupRef.cs
- Compiler.cs
- PeerEndPoint.cs
- MimeMapping.cs
- ProcessThreadCollection.cs
- MailAddress.cs
- NavigationProperty.cs
- SchemaConstraints.cs
- PrintPageEvent.cs
- HttpClientCertificate.cs
- Win32.cs
- CheckoutException.cs
- RawStylusInput.cs
- TextElementAutomationPeer.cs
- ContextMenuService.cs
- TypeSemantics.cs
- ChannelManagerBase.cs
- RecognizerInfo.cs
- HttpChannelListener.cs
- XsdDateTime.cs
- SimpleHandlerFactory.cs
- StateManagedCollection.cs
- DesignTimeVisibleAttribute.cs
- Faults.cs
- SweepDirectionValidation.cs
- Timeline.cs
- DataGridViewCellStyleChangedEventArgs.cs
- AssertUtility.cs
- FileDialogCustomPlace.cs
- DataRelationPropertyDescriptor.cs
- UrlUtility.cs
- ToolStripItemBehavior.cs
- securitycriticaldataClass.cs
- DesignObjectWrapper.cs
- SparseMemoryStream.cs
- EventsTab.cs
- PreservationFileWriter.cs
- StateFinalizationDesigner.cs
- IndexedGlyphRun.cs
- WebPartConnectionCollection.cs
- DefaultPropertyAttribute.cs
- TemplateInstanceAttribute.cs
- SelectionRange.cs
- ConfigurationElement.cs
- Baml2006ReaderFrame.cs
- WebScriptServiceHost.cs
- Mappings.cs
- RootBrowserWindowProxy.cs
- TimersDescriptionAttribute.cs
- PackageStore.cs
- DeclarativeConditionsCollection.cs
- CounterNameConverter.cs
- HttpResponseInternalBase.cs
- CodeAttributeArgument.cs
- Splitter.cs
- XmlSchemaProviderAttribute.cs
- ModelPropertyCollectionImpl.cs
- SqlBulkCopyColumnMappingCollection.cs
- SplashScreen.cs
- DbConnectionHelper.cs
- PtsPage.cs
- SmtpReplyReaderFactory.cs
- TextLineBreak.cs
- _NtlmClient.cs
- CodeAssignStatement.cs
- PartialCachingAttribute.cs
- DrawingServices.cs
- XmlNamespaceManager.cs
- SQLMoney.cs
- PeerObject.cs
- OrderablePartitioner.cs
- RegexMatchCollection.cs
- _NativeSSPI.cs
- Calendar.cs
- PathNode.cs
- Wildcard.cs
- Rect3DValueSerializer.cs
- WebPartConnectionsEventArgs.cs
- Int32AnimationBase.cs
- CultureSpecificCharacterBufferRange.cs
- SetterBase.cs
- OverrideMode.cs
- HttpSessionStateWrapper.cs
- AddInDeploymentState.cs
- FormatConvertedBitmap.cs
- _emptywebproxy.cs
- BuildTopDownAttribute.cs
- CombinedGeometry.cs
- GlyphRun.cs
- ObservableDictionary.cs
- Guid.cs
- SafeCoTaskMem.cs
- WaitHandle.cs
- BaseCodeDomTreeGenerator.cs
- Int32Storage.cs
- RoutedEventHandlerInfo.cs
- SHA512CryptoServiceProvider.cs
- BrowserCapabilitiesFactory.cs