Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / InteropServices / TCEAdapterGen / EventSinkHelperWriter.cs / 1305376 / 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; using System.Diagnostics.Contracts; 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(); Contract.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" ); Contract.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 Contract.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 ); Contract.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; } } // 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; using System; using System.Reflection; using System.Reflection.Emit; using System.Collections; using System.Diagnostics.Contracts; 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(); Contract.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" ); Contract.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 Contract.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 ); Contract.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; } } // 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
- ResourcePool.cs
- ModulesEntry.cs
- PeerCollaboration.cs
- ProcessManager.cs
- DataGridViewLinkCell.cs
- OleDbRowUpdatedEvent.cs
- mediapermission.cs
- LogWriteRestartAreaState.cs
- RectangleF.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- ItemList.cs
- WorkflowTransactionService.cs
- SerializationObjectManager.cs
- ConnectionsZoneDesigner.cs
- DataServiceException.cs
- AssemblyAssociatedContentFileAttribute.cs
- Int32AnimationUsingKeyFrames.cs
- ListViewItem.cs
- ScaleTransform.cs
- ObjectListShowCommandsEventArgs.cs
- FamilyTypefaceCollection.cs
- EncryptedKey.cs
- Transform3D.cs
- GetReadStreamResult.cs
- PointAnimationBase.cs
- ScriptIgnoreAttribute.cs
- WebServiceTypeData.cs
- EncryptedPackage.cs
- Color.cs
- DataTableClearEvent.cs
- SafeCryptContextHandle.cs
- CodeChecksumPragma.cs
- ColorDialog.cs
- HttpContextServiceHost.cs
- ThumbAutomationPeer.cs
- XamlPoint3DCollectionSerializer.cs
- ClipboardData.cs
- DataGridViewHeaderCell.cs
- FontStretches.cs
- objectquery_tresulttype.cs
- HttpPostClientProtocol.cs
- IgnoreDataMemberAttribute.cs
- SqlVersion.cs
- IisTraceListener.cs
- SingleAnimationUsingKeyFrames.cs
- IsolatedStorageFilePermission.cs
- CellParagraph.cs
- Parser.cs
- DoubleConverter.cs
- HiddenField.cs
- HtmlImage.cs
- WebControlAdapter.cs
- DetailsViewInsertEventArgs.cs
- CompareValidator.cs
- WebPartConnectionsDisconnectVerb.cs
- BaseUriHelper.cs
- ProcessingInstructionAction.cs
- StandardBindingCollectionElement.cs
- WebAdminConfigurationHelper.cs
- StringUtil.cs
- SoapFormatterSinks.cs
- PageAdapter.cs
- ContourSegment.cs
- PropertyTabChangedEvent.cs
- UnsafeNativeMethods.cs
- DocumentOrderQuery.cs
- CommentEmitter.cs
- SqlClientPermission.cs
- AccessDataSourceView.cs
- ViewBase.cs
- Brush.cs
- HebrewCalendar.cs
- PrivacyNoticeElement.cs
- PolyQuadraticBezierSegment.cs
- FilterableAttribute.cs
- GridProviderWrapper.cs
- BinaryWriter.cs
- PageContentAsyncResult.cs
- BrushMappingModeValidation.cs
- Style.cs
- InteropAutomationProvider.cs
- HttpSocketManager.cs
- SoapCommonClasses.cs
- ProfileGroupSettings.cs
- CodeConstructor.cs
- HostProtectionPermission.cs
- FontNameEditor.cs
- MediaScriptCommandRoutedEventArgs.cs
- ExecutionContext.cs
- UserControlBuildProvider.cs
- TimeoutException.cs
- XmlCompatibilityReader.cs
- DataControlButton.cs
- Image.cs
- SqlWebEventProvider.cs
- Helper.cs
- DtrList.cs
- ZipQueryOperator.cs
- WebPartZoneCollection.cs
- FixedLineResult.cs