Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- XmlQuerySequence.cs
- PassportAuthenticationEventArgs.cs
- Misc.cs
- GeneralTransform2DTo3DTo2D.cs
- Iis7Helper.cs
- HttpRequestWrapper.cs
- SpecialTypeDataContract.cs
- AnnotationHelper.cs
- UnauthorizedWebPart.cs
- GridViewColumnCollection.cs
- MenuTracker.cs
- LongMinMaxAggregationOperator.cs
- CryptoConfig.cs
- UidManager.cs
- Pkcs7Recipient.cs
- GridViewColumnHeader.cs
- InvalidEnumArgumentException.cs
- CaseStatementSlot.cs
- PrePostDescendentsWalker.cs
- IIS7UserPrincipal.cs
- WebPartExportVerb.cs
- safemediahandle.cs
- embossbitmapeffect.cs
- BitmapEffectCollection.cs
- CodeTypeParameter.cs
- DetailsViewPagerRow.cs
- Predicate.cs
- SiteMapNodeCollection.cs
- SimpleHandlerFactory.cs
- UInt16Converter.cs
- SafeNativeMethodsMilCoreApi.cs
- CharAnimationUsingKeyFrames.cs
- TraceEventCache.cs
- TextTreeUndoUnit.cs
- CodeRemoveEventStatement.cs
- DropTarget.cs
- LocatorManager.cs
- PersonalizationStateInfoCollection.cs
- ThreadAttributes.cs
- CommonDialog.cs
- IImplicitResourceProvider.cs
- ResolvedKeyFrameEntry.cs
- SecurityCriticalDataForSet.cs
- WithStatement.cs
- UndoUnit.cs
- FixUpCollection.cs
- DummyDataSource.cs
- RemoteWebConfigurationHostStream.cs
- BooleanConverter.cs
- GregorianCalendar.cs
- CommandArguments.cs
- MetadataItem_Static.cs
- PagePropertiesChangingEventArgs.cs
- ListManagerBindingsCollection.cs
- ColumnBinding.cs
- FontFamily.cs
- _TimerThread.cs
- DataGridViewLinkCell.cs
- JumpItem.cs
- RealizedColumnsBlock.cs
- ChtmlFormAdapter.cs
- BaseInfoTable.cs
- CustomGrammar.cs
- controlskin.cs
- XamlStyleSerializer.cs
- LicenseException.cs
- WindowPatternIdentifiers.cs
- ObjectStateEntryBaseUpdatableDataRecord.cs
- AddInToken.cs
- NativeRightsManagementAPIsStructures.cs
- ValueUnavailableException.cs
- GenericRootAutomationPeer.cs
- ListViewItemEventArgs.cs
- KeyValuePairs.cs
- SelectorItemAutomationPeer.cs
- CompatibleComparer.cs
- Root.cs
- EventMappingSettingsCollection.cs
- TreeNode.cs
- NewItemsContextMenuStrip.cs
- CommonDialog.cs
- CodeValidator.cs
- SpeechAudioFormatInfo.cs
- TextRunProperties.cs
- CollectionDataContract.cs
- RowSpanVector.cs
- DbDataAdapter.cs
- BrowserCapabilitiesCodeGenerator.cs
- SafeFindHandle.cs
- ThicknessAnimation.cs
- PerformanceCounterPermission.cs
- ParseNumbers.cs
- BlockUIContainer.cs
- SortKey.cs
- CodeGen.cs
- LinqMaximalSubtreeNominator.cs
- NumericUpDownAcceleration.cs
- SynchronizationContext.cs
- ProfessionalColors.cs
- NoClickablePointException.cs