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
- PassportAuthenticationEventArgs.cs
- SecurityDocument.cs
- DrawingBrush.cs
- SecurityPermission.cs
- LedgerEntryCollection.cs
- Permission.cs
- SolidColorBrush.cs
- SQLDouble.cs
- MediaContext.cs
- DeviceSpecificChoiceCollection.cs
- Empty.cs
- ReturnEventArgs.cs
- MediaScriptCommandRoutedEventArgs.cs
- ItemsChangedEventArgs.cs
- XamlPathDataSerializer.cs
- FixedPosition.cs
- ConnectionInterfaceCollection.cs
- TreeViewEvent.cs
- xsdvalidator.cs
- VerificationException.cs
- ColorContext.cs
- TypeDescriptionProviderAttribute.cs
- SafeIUnknown.cs
- MonitoringDescriptionAttribute.cs
- CookieHandler.cs
- ScrollViewer.cs
- SqlConnectionPoolGroupProviderInfo.cs
- basemetadatamappingvisitor.cs
- OrderingInfo.cs
- MeshGeometry3D.cs
- XmlSchemaSimpleContentRestriction.cs
- ColumnResizeUndoUnit.cs
- PageCodeDomTreeGenerator.cs
- ExpressionsCollectionConverter.cs
- StyleHelper.cs
- ISSmlParser.cs
- WebPartRestoreVerb.cs
- ScriptManagerProxy.cs
- RolePrincipal.cs
- ProcessHostConfigUtils.cs
- XmlCharacterData.cs
- SoapObjectWriter.cs
- Label.cs
- OutOfProcStateClientManager.cs
- InternalSafeNativeMethods.cs
- BitmapVisualManager.cs
- FilteredAttributeCollection.cs
- BamlRecordHelper.cs
- VirtualPathProvider.cs
- XmlMessageFormatter.cs
- ProvidersHelper.cs
- base64Transforms.cs
- Token.cs
- XmlLinkedNode.cs
- Trace.cs
- AudioSignalProblemOccurredEventArgs.cs
- InputScope.cs
- MetadataCache.cs
- AssertUtility.cs
- OleDbCommandBuilder.cs
- Rect3D.cs
- TransactionFlowAttribute.cs
- PackWebRequest.cs
- HandlerBase.cs
- TableCellCollection.cs
- HostedTransportConfigurationManager.cs
- BamlResourceContent.cs
- XmlSchemaAny.cs
- TagPrefixAttribute.cs
- TextParagraphCache.cs
- StylusPointDescription.cs
- _Events.cs
- EntryWrittenEventArgs.cs
- DoubleConverter.cs
- DelegatedStream.cs
- MeasurementDCInfo.cs
- OdbcEnvironmentHandle.cs
- KeyValueSerializer.cs
- DataGridViewEditingControlShowingEventArgs.cs
- ByteStreamGeometryContext.cs
- ColorAnimation.cs
- WrappedIUnknown.cs
- CollectionsUtil.cs
- XPathDocumentIterator.cs
- CoordinationService.cs
- ImpersonateTokenRef.cs
- SimpleTextLine.cs
- TypeElementCollection.cs
- XmlElementCollection.cs
- InputLanguage.cs
- MachineKey.cs
- OracleBinary.cs
- RuntimeResourceSet.cs
- ControlParameter.cs
- LabelDesigner.cs
- TransformerTypeCollection.cs
- LayoutManager.cs
- DLinqTableProvider.cs
- BitmapCacheBrush.cs
- SoapExtensionReflector.cs