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
- LocatorGroup.cs
- HostedHttpRequestAsyncResult.cs
- OneWayElement.cs
- TextBoxLine.cs
- IdnElement.cs
- PositiveTimeSpanValidator.cs
- VersionPair.cs
- BinaryFormatterWriter.cs
- XamlSerializationHelper.cs
- GridViewRow.cs
- BufferedGraphicsContext.cs
- BrowsableAttribute.cs
- CodeAttributeArgumentCollection.cs
- WindowsNonControl.cs
- CodeDirectionExpression.cs
- BitmapEffectGroup.cs
- PowerEase.cs
- Timeline.cs
- WebBrowserDesigner.cs
- DivideByZeroException.cs
- TextParaClient.cs
- SourceLocationProvider.cs
- TextInfo.cs
- XmlSchemaAny.cs
- SystemException.cs
- XomlDesignerLoader.cs
- WebException.cs
- SchemaNotation.cs
- SmtpMail.cs
- TextEvent.cs
- StandardToolWindows.cs
- ClientUIRequest.cs
- WebBrowserSiteBase.cs
- CommandHelpers.cs
- TextTreeObjectNode.cs
- AttachedPropertyDescriptor.cs
- SettingsPropertyIsReadOnlyException.cs
- AttributedMetaModel.cs
- CustomError.cs
- SequenceFullException.cs
- CurrentChangingEventManager.cs
- WorkItem.cs
- HttpResponseInternalWrapper.cs
- DoubleConverter.cs
- JsonReader.cs
- SelectionItemPattern.cs
- CellNormalizer.cs
- ConfigXmlAttribute.cs
- TextEditorSelection.cs
- TransmissionStrategy.cs
- RegexCompiler.cs
- TextSelectionHelper.cs
- MatrixIndependentAnimationStorage.cs
- PropertyCollection.cs
- SafeLibraryHandle.cs
- SqlDataAdapter.cs
- SmiGettersStream.cs
- UIServiceHelper.cs
- Membership.cs
- GeneralTransform3DTo2D.cs
- SqlPersonalizationProvider.cs
- MaskedTextBox.cs
- future.cs
- DataGridCell.cs
- DragAssistanceManager.cs
- Tokenizer.cs
- PageAsyncTask.cs
- TypeDependencyAttribute.cs
- TokenFactoryCredential.cs
- SchemaInfo.cs
- WebZoneDesigner.cs
- SimpleExpression.cs
- DeploymentSection.cs
- DesignConnectionCollection.cs
- RsaKeyIdentifierClause.cs
- MessageHeaderT.cs
- DataRowComparer.cs
- CuspData.cs
- _ContextAwareResult.cs
- Mouse.cs
- TimelineCollection.cs
- DependencyPropertyKind.cs
- Size3D.cs
- SortQuery.cs
- ForceCopyBuildProvider.cs
- RegistryPermission.cs
- GlyphingCache.cs
- SpnegoTokenProvider.cs
- ScriptingJsonSerializationSection.cs
- Model3DCollection.cs
- CapabilitiesState.cs
- AppSettingsSection.cs
- safesecurityhelperavalon.cs
- DebugView.cs
- MouseGestureValueSerializer.cs
- DataPointer.cs
- EdmItemCollection.cs
- DPCustomTypeDescriptor.cs
- Int16KeyFrameCollection.cs
- ComponentResourceManager.cs