Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PreviewPageInfo.cs
- MemberProjectedSlot.cs
- CodeSubDirectory.cs
- SpinLock.cs
- XmlSchemaSimpleTypeRestriction.cs
- UnsafeNativeMethods.cs
- StrokeCollection2.cs
- WindowsFormsSynchronizationContext.cs
- BaseWebProxyFinder.cs
- TreeNodeMouseHoverEvent.cs
- TemplateEditingFrame.cs
- DocumentCollection.cs
- ObjectReferenceStack.cs
- ProxySimple.cs
- CrossContextChannel.cs
- SiteMapDataSource.cs
- DayRenderEvent.cs
- Int16Converter.cs
- GradientStopCollection.cs
- DataControlPagerLinkButton.cs
- InvalidProgramException.cs
- ParallelTimeline.cs
- TrackingStringDictionary.cs
- Cursor.cs
- ActivityStateRecord.cs
- CompiledQuery.cs
- XD.cs
- FileNotFoundException.cs
- QuaternionValueSerializer.cs
- DynamicILGenerator.cs
- Enum.cs
- ChannelAcceptor.cs
- ObjectHandle.cs
- Facet.cs
- PropertyGridView.cs
- ResourcePermissionBaseEntry.cs
- XamlReader.cs
- LogWriteRestartAreaState.cs
- CompositeCollection.cs
- OdbcParameter.cs
- CollectionContainer.cs
- BitmapImage.cs
- CacheDict.cs
- LeaseManager.cs
- PcmConverter.cs
- SubtreeProcessor.cs
- DesignTimeHTMLTextWriter.cs
- QuotedPrintableStream.cs
- KeyProperty.cs
- DefaultShape.cs
- ApplicationCommands.cs
- Item.cs
- SignatureDescription.cs
- ObjectListShowCommandsEventArgs.cs
- ChannelPoolSettings.cs
- FileRegion.cs
- DropTarget.cs
- NumericUpDownAccelerationCollection.cs
- XmlSchemaParticle.cs
- ToolTipService.cs
- BigInt.cs
- ComponentConverter.cs
- TraceUtils.cs
- WebBrowserNavigatingEventHandler.cs
- DataErrorValidationRule.cs
- DesignerLoader.cs
- TextTreeInsertElementUndoUnit.cs
- TextTreeUndoUnit.cs
- DynamicResourceExtension.cs
- HttpContextBase.cs
- ProfileGroupSettingsCollection.cs
- AppSettingsSection.cs
- JoinElimination.cs
- PaperSource.cs
- ScrollEvent.cs
- AppDomainProtocolHandler.cs
- CreateRefExpr.cs
- RootProfilePropertySettingsCollection.cs
- SelectionHighlightInfo.cs
- CellParagraph.cs
- NumberFunctions.cs
- InheritanceContextHelper.cs
- ObjectItemCollection.cs
- MessageBox.cs
- DeflateEmulationStream.cs
- TriggerActionCollection.cs
- CodePropertyReferenceExpression.cs
- SettingsBindableAttribute.cs
- PlaceHolder.cs
- DbDataRecord.cs
- KeySpline.cs
- Size.cs
- DocumentPageViewAutomationPeer.cs
- SchemaMerger.cs
- QuotedStringFormatReader.cs
- StandardMenuStripVerb.cs
- Group.cs
- DrawingImage.cs
- DefaultSettingsSection.cs
- XmlQueryContext.cs