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 / 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; } } // 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; 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; } } // 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
- EDesignUtil.cs
- XmlDictionary.cs
- PauseStoryboard.cs
- SystemWebCachingSectionGroup.cs
- UpDownBaseDesigner.cs
- RawKeyboardInputReport.cs
- SubtreeProcessor.cs
- WebSysDisplayNameAttribute.cs
- CodeSnippetTypeMember.cs
- DbConnectionClosed.cs
- CheckBoxList.cs
- TableLayoutStyle.cs
- WebPartEventArgs.cs
- TreeNodeBindingCollection.cs
- PenThreadWorker.cs
- TypeDescriptor.cs
- PointValueSerializer.cs
- Content.cs
- ProfilePropertyNameValidator.cs
- TableDetailsRow.cs
- GregorianCalendar.cs
- Parser.cs
- WindowPattern.cs
- _AutoWebProxyScriptHelper.cs
- TypeSystem.cs
- DecimalConverter.cs
- DesignerCatalogPartChrome.cs
- SoapIncludeAttribute.cs
- KeyPullup.cs
- SoapUnknownHeader.cs
- EDesignUtil.cs
- SqlClientWrapperSmiStreamChars.cs
- DataGridViewSelectedRowCollection.cs
- ProcessModuleCollection.cs
- XamlGridLengthSerializer.cs
- CounterSetInstance.cs
- PictureBox.cs
- regiisutil.cs
- SqlPersonalizationProvider.cs
- Win32SafeHandles.cs
- DbConnectionClosed.cs
- EditableTreeList.cs
- ComplexObject.cs
- ManagementOperationWatcher.cs
- XamlFigureLengthSerializer.cs
- SupportingTokenParameters.cs
- MessageDescriptionCollection.cs
- FillBehavior.cs
- MatrixCamera.cs
- DisplayMemberTemplateSelector.cs
- Codec.cs
- ToolStripSplitButton.cs
- RegexRunner.cs
- ApplicationDirectory.cs
- GeneratedContractType.cs
- Select.cs
- XPathParser.cs
- QuaternionAnimationUsingKeyFrames.cs
- DuplicateWaitObjectException.cs
- SizeAnimation.cs
- RuntimeEnvironment.cs
- SetterBaseCollection.cs
- panel.cs
- UniqueIdentifierService.cs
- CopyCodeAction.cs
- VirtualPathUtility.cs
- OracleBinary.cs
- Transform.cs
- StagingAreaInputItem.cs
- FieldMetadata.cs
- RenderDataDrawingContext.cs
- QilLiteral.cs
- MouseGesture.cs
- OdbcConnectionFactory.cs
- EncodingDataItem.cs
- CodeEventReferenceExpression.cs
- BinaryCommonClasses.cs
- CodeRegionDirective.cs
- ObjectSpanRewriter.cs
- XmlSchemaComplexContentExtension.cs
- CopyOnWriteList.cs
- IndentedWriter.cs
- AutomationPropertyInfo.cs
- WsdlBuildProvider.cs
- UIElementAutomationPeer.cs
- Point4D.cs
- ActiveXHost.cs
- DataSourceHelper.cs
- LocalizeDesigner.cs
- COM2FontConverter.cs
- DateTimeFormatInfoScanner.cs
- XMLSyntaxException.cs
- CodeTypeConstructor.cs
- ValidatorCollection.cs
- GridViewRowPresenterBase.cs
- MultiView.cs
- StaticSiteMapProvider.cs
- ElasticEase.cs
- XmlSignatureManifest.cs
- SimpleTextLine.cs