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
- ValidatedControlConverter.cs
- SpotLight.cs
- UrlMapping.cs
- SubpageParagraph.cs
- BitmapEffect.cs
- DbProviderFactory.cs
- AutomationPropertyChangedEventArgs.cs
- StringResourceManager.cs
- WSTrustFeb2005.cs
- DataGrid.cs
- WorkflowRuntimeService.cs
- FieldTemplateUserControl.cs
- DecoratedNameAttribute.cs
- RegionIterator.cs
- WizardPanel.cs
- GeometryValueSerializer.cs
- CopyCodeAction.cs
- x509utils.cs
- PersonalizablePropertyEntry.cs
- GridLength.cs
- FindProgressChangedEventArgs.cs
- ApplicationFileCodeDomTreeGenerator.cs
- SqlParameterCollection.cs
- MsmqIntegrationBinding.cs
- _LoggingObject.cs
- RefType.cs
- ServicesUtilities.cs
- ScriptResourceHandler.cs
- PartitionerQueryOperator.cs
- ButtonBaseAutomationPeer.cs
- oledbmetadatacollectionnames.cs
- Expression.cs
- DWriteFactory.cs
- WebPartMenuStyle.cs
- XmlEnumAttribute.cs
- ProcessManager.cs
- NativeMethods.cs
- OleAutBinder.cs
- TimeSpanHelper.cs
- Char.cs
- StructuralType.cs
- TypeCollectionDesigner.xaml.cs
- ToolStripDropDown.cs
- ComponentConverter.cs
- PageParser.cs
- sqlnorm.cs
- EmptyStringExpandableObjectConverter.cs
- ClientApiGenerator.cs
- CollectionCodeDomSerializer.cs
- AssemblyCollection.cs
- Site.cs
- AsyncResult.cs
- BooleanSwitch.cs
- LambdaExpression.cs
- PackageDigitalSignature.cs
- XmlEntityReference.cs
- AssociationSetMetadata.cs
- ImageButton.cs
- CodeCompiler.cs
- TablePattern.cs
- DataColumnMapping.cs
- HtmlObjectListAdapter.cs
- PrintDocument.cs
- SmtpReplyReader.cs
- DesignColumn.cs
- TreeNodeCollection.cs
- SelectionRange.cs
- DataSourceControlBuilder.cs
- ScriptManager.cs
- ProgressBar.cs
- BmpBitmapDecoder.cs
- BitmapEffectGroup.cs
- GeneralTransform3D.cs
- SQLBytesStorage.cs
- Attributes.cs
- NonParentingControl.cs
- documentsequencetextcontainer.cs
- PauseStoryboard.cs
- IndentTextWriter.cs
- listitem.cs
- MissingFieldException.cs
- CompiledQueryCacheKey.cs
- Fault.cs
- WebControlAdapter.cs
- PropertyFilterAttribute.cs
- FlowDocumentReader.cs
- DataListItemEventArgs.cs
- SqlBulkCopyColumnMappingCollection.cs
- PathSegmentCollection.cs
- CaseInsensitiveOrdinalStringComparer.cs
- SByteConverter.cs
- ObjectStateManagerMetadata.cs
- EntryWrittenEventArgs.cs
- RightsManagementInformation.cs
- TextClipboardData.cs
- FontDriver.cs
- HttpConfigurationContext.cs
- UpdatePanel.cs
- Drawing.cs
- MimeBasePart.cs