private void CreateField(TypeInfo type, TypeAttr attr, VarDesc var, ref bool isConversionLoss) { TypeDesc fieldTypeDesc = var.elemdescVar.tdesc; TypeConverter typeConverter = new TypeConverter(m_info, type, fieldTypeDesc, ConversionType.Field); Type fieldType = typeConverter.ConvertedType; string fieldName = type.GetDocumentation(var.memid); FieldBuilder field = m_typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public); typeConverter.ApplyAttributes(field); isConversionLoss |= typeConverter.IsConversionLoss; // // Emit ComConversionLossAttribute for fields if necessary // if (typeConverter.IsConversionLoss) { field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); // // Emit Wrn_UnconvertableField warning // m_info.ReportEvent( WarningCode.Wrn_UnconvertableField, Resource.FormatString("Wrn_UnconvertableField", type.GetDocumentation(), fieldName)); } // // Emit TypeLibVarAttribute if necessary // if (var.wVarFlags != 0) { field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibVar((TypeLibVarFlags)var.wVarFlags)); } }
public AssemblyBuilder CreateAssemblyBuilder(AssemblyName name, TypeLib tlb, TypeLibImporterFlags flags) { using (TypeLibAttr attr = tlb.GetLibAttr()) { // New assembly as well as loaded assembly should be all in a ReflectionOnly context as we don't need to run the code AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly); // Handle the type library name assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForImportedFromTypeLib(tlb.GetDocumentation())); // Handle the type library version assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibVersion(attr.wMajorVerNum, attr.wMinorVerNum)); // Handle the LIBID assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForGuid(attr.guid)); // If we are generating a PIA, then set the PIA custom attribute. if ((flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0) { assemblyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForPrimaryInteropAssembly(attr.wMajorVerNum, attr.wMinorVerNum)); } return(assemblyBuilder); } }
protected override void OnDefineType() { TypeInfo typeInfo = RefNonAliasedTypeInfo; // Creates the enum type m_typeBuilder = ConvCommon.DefineTypeHelper( m_info, RefTypeInfo, RefNonAliasedTypeInfo, TypeAttributes.Public | TypeAttributes.Sealed, typeof(Enum), ConvType.Enum ); // The field must be created here so that TypeBuilder can calculate a hash... // Need to create a special field to hold the enum data FieldBuilder field = m_typeBuilder.DefineField( "value__", typeof(Int32), FieldAttributes.Public | FieldAttributes.SpecialName); // Handle [TypeLibType(...)] if evaluate to non-0 using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr()) { if (refTypeAttr.wTypeFlags != 0) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags)); } } m_info.AddToSymbolTable(RefTypeInfo, ConvType.Enum, this); m_info.RegisterType(m_typeBuilder, this); }
/// <summary> /// Does the type need custom marshaler for marshalling? /// </summary> /// <returns>Whether we need to use custom marshaler</returns> private bool TryUseCustomMarshaler(Guid iid, out Type result) { result = null; if (iid == WellKnownGuids.IID_IDispatchEx) { Type type = typeof(System.Runtime.InteropServices.CustomMarshalers.ExpandoToDispatchExMarshaler); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsCustomMarshaler(type, "IExpando"); SetUnmanagedType(UnmanagedType.CustomMarshaler); result = typeof(System.Runtime.InteropServices.Expando.IExpando); return(true); } else if (iid == WellKnownGuids.IID_IEnumVARIANT) { Type type = typeof(System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsCustomMarshaler(type, null); SetUnmanagedType(UnmanagedType.CustomMarshaler); result = typeof(System.Collections.IEnumerator); return(true); } else if (iid == WellKnownGuids.IID_ITypeInfo) { Type type = typeof(System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsCustomMarshaler(type, null); SetUnmanagedType(UnmanagedType.CustomMarshaler); result = typeof(Type); return(true); } return(false); }
protected override void OnDefineType() { TypeInfo typeInfo = RefNonAliasedTypeInfo; m_typeBuilder = ConvCommon.DefineTypeHelper( m_info, RefTypeInfo, RefNonAliasedTypeInfo, TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.ExplicitLayout, typeof(ValueType), ConvType.Union ); // Handle [TypeLibType(...)] if evaluate to non-0 using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr()) { if (refTypeAttr.wTypeFlags != 0) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags)); } } m_info.AddToSymbolTable(RefTypeInfo, ConvType.Union, this); m_info.RegisterType(m_typeBuilder, this); }
public void SetDefaultMember(TypeBuilder typeBuilder, string name) { if (!m_defaultMemberTable.ContainsKey(typeBuilder)) { typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForDefaultMember(name)); m_defaultMemberTable.Add(typeBuilder, true); } }
/// <summary> /// Get the event delegate for specified method in the source interface. Create a new one if necessary /// </summary> /// <param name="index">Function index</param> /// <returns>The delegate type</returns> public Type GetEventDelegate(InterfaceMemberInfo memberInfo) { TypeInfo type = memberInfo.RefTypeInfo; using (TypeAttr attr = type.GetTypeAttr()) { // Create m_delegateTypes on demand if (m_delegateTypes == null) { m_delegateTypes = new Dictionary <InterfaceMemberInfo, Type>(); } // // Check if we already have a delegate type for method n // if (!m_delegateTypes.ContainsKey(memberInfo)) { // // If not, create a new delegate // FuncDesc func = type.GetFuncDesc(memberInfo.Index); string eventName = type.GetDocumentation(func.memid); string delegateName = m_info.GetRecommendedManagedName(m_convInterface.RefTypeInfo, ConvType.Interface, true) + "_" + type.GetDocumentation(func.memid) + "EventHandler"; // Deal with name collisions delegateName = m_info.GetUniqueManagedName(delegateName); TypeBuilder delegateTypeBuilder = m_info.ModuleBuilder.DefineType( delegateName, TypeAttributes.Public | TypeAttributes.Sealed, typeof(MulticastDelegate) ); // Create constructor for the delegate ConstructorBuilder delegateCtorBuilder = delegateTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { typeof(Object), typeof(UIntPtr) }); delegateCtorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); // Create methods for the delegate InterfaceInfo interfaceInfoForDelegate = new InterfaceInfo(m_info, delegateTypeBuilder, false, type, attr, false, true); interfaceInfoForDelegate.AllowNewEnum = !m_convInterface.ImplementsIEnumerable; ConvCommon.CreateMethodForDelegate(interfaceInfoForDelegate, func, memberInfo.Index); // Emit ComVisibleAttribute(false) delegateTypeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComVisible(false)); // Emit TypeLibTypeAttribute(TypeLibTypeFlags.FHidden) to hide it from object browser in VB delegateTypeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType(TypeLibTypeFlags.FHidden)); // Create the delegate m_delegateTypes[memberInfo] = delegateTypeBuilder.CreateType(); } } return(m_delegateTypes[memberInfo]); }
public override void OnCreate() { string name = ManagedName; if (m_type != null) { return; } TypeInfo typeInfo = RefNonAliasedTypeInfo; using (TypeAttr typeAttr = typeInfo.GetTypeAttr()) { // // Create fields // int cVars = typeAttr.cVars; bool isConversionLoss = false; for (int n = 0; n < cVars; ++n) { using (VarDesc var = typeInfo.GetVarDesc(n)) { CreateField(typeInfo, typeAttr, var, ref isConversionLoss); } } // // Emit StructLayout(LayoutKind.Sequential, Pack=cbAlignment) // m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForStructLayout(LayoutKind.Explicit, typeAttr.cbAlignment, typeAttr.cbSizeInstance)); // // Emit ComConversionLossAttribute if necessary // if (isConversionLoss) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); } // // Emit SerializableAttribute for /transform:serializablevalueclasses // if ((m_info.Settings.m_flags & TypeLibImporterFlags.SerializableValueClasses) != 0) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSerializable()); } m_type = m_typeBuilder.CreateType(); } }
private void CreateField(TypeInfo type, TypeAttr attr, VarDesc var, ref bool isConversionLoss) { if (IsObjectType(type, var.elemdescVar.tdesc)) { isConversionLoss = true; } else { TypeConverter typeConverter = new TypeConverter(m_info, type, var.elemdescVar.tdesc, ConversionType.Field); Type fieldType = typeConverter.ConvertedType; // TlbImp2 will only skip reference types, instead of skipping every field // Also, TlbImp1 will skip ValueType *, which doesn't make any sense. TlbImp2 will keep ValueType * as IntPtr string fieldName = type.GetDocumentation(var.memid); // Generates the [FieldOffset(0)] layout declarations that approximate unions in managed code FieldBuilder field = m_typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public); field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForFieldOffset(0)); typeConverter.ApplyAttributes(field); isConversionLoss |= typeConverter.IsConversionLoss; // // Emit ComConversionLossAttribute for fields if necessary // if (typeConverter.IsConversionLoss) { field.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); // // Emit Wrn_UnconvertableField warning // m_info.ReportEvent( WarningCode.Wrn_UnconvertableField, Resource.FormatString("Wrn_UnconvertableField", type.GetDocumentation(), fieldName)); } } }
protected override void OnDefineType() { TypeInfo typeInfo = RefNonAliasedTypeInfo; using (TypeAttr typeAttr = typeInfo.GetTypeAttr()) { string name = m_info.GetUniqueManagedName(RefTypeInfo, ConvType.Module); // Create the managed type for the module // It should be abstract & sealed, which is the same as a static class in C# // Also, reflection will create a default constructor for you if the class has no constructor, // except if the class is interface, valuetype, enum, or a static class, so this works pretty well // except that this is slightly different than tlbimpv1, as tlbimpv1 the class is not sealed m_typeBuilder = m_info.ModuleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, typeof(Object)); // Handle [Guid(...)] custom attribute ConvCommon.DefineGuid(RefTypeInfo, RefNonAliasedTypeInfo, m_typeBuilder); // Handle [TypeLibType(...)] if evaluate to non-0 using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr()) { if (refTypeAttr.wTypeFlags != 0) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags)); } } } // Add to symbol table automatically m_info.AddToSymbolTable(RefTypeInfo, ConvType.Module, this); // Register type m_info.RegisterType(m_typeBuilder, this); }
protected void DefineType(ConverterInfo info, TypeInfo typeInfo, bool dealWithAlias) { m_info = info; m_typeInfo = typeInfo; if (dealWithAlias) { m_nonAliasedTypeInfo = ConvCommon.GetAlias(typeInfo); } else { m_nonAliasedTypeInfo = typeInfo; } try { OnDefineType(); // // Emit SuppressUnmanagedCodeSecurityAttribute for /unsafe switch // if ((m_info.Settings.m_flags & TypeLibImporterFlags.UnsafeInterfaces) != 0) { if (ConvType != ConvType.ClassInterface && ConvType != ConvType.EventInterface) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSuppressUnmanagedCodeSecurity()); } } } catch (ReflectionTypeLoadException) { throw; // Fatal failure. Throw } catch (TlbImpResolveRefFailWrapperException) { throw; // Fatal failure. Throw } catch (TlbImpGeneralException) { throw; // Fatal failure. Throw } catch (Exception) { string name = String.Empty; if (m_typeInfo != null) { try { name = m_typeInfo.GetDocumentation(); } catch (Exception) { } } if (name != String.Empty) { string msg = Resource.FormatString("Wrn_InvalidTypeInfo", name); m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo, msg); } else { string msg = Resource.FormatString("Wrn_InvalidTypeInfo_Unnamed"); m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo_Unnamed, msg); } // When failure, try to create the type anyway if (m_typeBuilder != null) { m_type = m_typeBuilder.CreateType(); } } }
/// <summary> /// Generate properties for Functions /// </summary> public void GenerateProperty(InterfaceInfo info, TypeBuilder typebuilder) { // Generate property using unique name string uniqueName = info.GenerateUniqueMemberName( m_propertyInfo.RecommendedName, null, MemberTypes.Property); // // Convert the signature // Type[] paramTypes = null; Type retType = null; if (m_propertyInfo.Kind == PropertyKind.VarProperty) { // Converting variable to property. There are no parameters at all TypeConverter typeConverter = m_propertyInfo.GetPropertyTypeConverter(info.ConverterInfo, info.RefTypeInfo); info.IsConversionLoss |= typeConverter.IsConversionLoss; retType = typeConverter.ConvertedType; } else { // If /preservesig is specified, do not generate property, and only // the getter and setter functions are enough. // Property requires that the property getter must return the real property value, and the first parameter of // the setter must be the property value. While, the /preservesig switch will change the prototype of the setters and // getters, which is different from what the compiler expected. // So we do not support the Property if the /preservesig is specified. if (info.ConverterInfo.Settings.m_isPreserveSig && (m_propertyInfo.BestFuncDesc != null && !m_propertyInfo.BestFuncDesc.IsDispatch)) { if (TlbImpCode.TlbImpCode.s_Options.m_bVerboseMode) { FormattedOutput.Output.WriteInfo(Resource.FormatString("Msg_PropertyIsOmitted", m_propertyInfo.RecommendedName, m_propertyInfo.RefTypeInfo.GetDocumentation()), MessageCode.Msg_PropertyIsOmitted); } return; } // Converting propget/propput/propputref functions to property. TypeConverter typeConverter = m_propertyInfo.GetPropertyTypeConverter(info.ConverterInfo, info.RefTypeInfo); retType = typeConverter.ConvertedType; info.IsConversionLoss |= typeConverter.IsConversionLoss; FuncDesc bestFuncDesc = m_propertyInfo.BestFuncDesc; // if we have a [vararg] int varArg, firstOptArg, lastOptArg; if (bestFuncDesc.cParamsOpt == -1) { ConvCommon.CheckForOptionalArguments(info.ConverterInfo, bestFuncDesc, out varArg, out firstOptArg, out lastOptArg); } else { varArg = -1; } List <Type> paramTypeList = new List <Type>(); // Find the index part of the property's signature bool skipLastRetVal = (bestFuncDesc.IsPropertyPut || bestFuncDesc.IsPropertyPutRef); for (int i = 0; i < bestFuncDesc.cParams; ++i) { ElemDesc elemDesc = bestFuncDesc.GetElemDesc(i); ParamDesc paramDesc = elemDesc.paramdesc; // Skip LCID/RetVal if (paramDesc.IsLCID || paramDesc.IsRetval) { continue; } // Skip the "new value" parameter for putters if (skipLastRetVal) { skipLastRetVal = false; continue; } ConversionType conversionType; if (i == varArg) { conversionType = ConversionType.VarArgParameter; } else { conversionType = ConversionType.Parameter; } TypeConverter paramTypeConverter = new TypeConverter(info.ConverterInfo, info.RefTypeInfo, elemDesc.tdesc, conversionType); info.IsConversionLoss |= paramTypeConverter.IsConversionLoss; paramTypeList.Add(paramTypeConverter.ConvertedType); } paramTypes = paramTypeList.ToArray(); } // Define the property PropertyBuilder propertyBuilder = typebuilder.DefineProperty(uniqueName, PropertyAttributes.HasDefault, retType, paramTypes); if (info.IsCoClass && !info.IsDefaultInterface) { // Skip non-default interfaces / implemented interfaces (when we are creating coclass) } else { // Emit dispatch id attribute propertyBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForDispId(m_propertyInfo.DispId)); } // We don't need to emit MarshalAs for properties because the get/set functions should already have them // Emitting MarshalAs for property will hang up CLR!! if (m_methodGet != null) { propertyBuilder.SetGetMethod(m_methodGet); } // Has both propPut & propPutRef? if (m_methodPut != null && m_methodPutRef != null) { propertyBuilder.SetSetMethod(m_methodPutRef); propertyBuilder.AddOtherMethod(m_methodPut); } else { if (m_methodPut != null) { propertyBuilder.SetSetMethod(m_methodPut); } else if (m_methodPutRef != null) { propertyBuilder.SetSetMethod(m_methodPutRef); } } // // Handle DefaultMemberAttribute // if (m_propertyInfo.DispId == WellKnownDispId.DISPID_VALUE) { // DIFF: TlbImpv1 use the type library name while we use the unique name info.ConverterInfo.SetDefaultMember(info.TypeBuilder, uniqueName); } // Handle alias information ConvCommon.HandleAlias(info.ConverterInfo, info.RefTypeInfo, m_propertyInfo.PropertyTypeDesc, propertyBuilder); }
private void _Convert() { VarEnum vt = (VarEnum)m_typeDesc.vt; // Strip out VT_PTR while (vt == VarEnum.VT_PTR) { m_typeDesc = m_typeDesc.lptdesc; vt = (VarEnum)m_typeDesc.vt; m_nativeIndirections++; } // Strip out VT_BYREF if ((vt & VarEnum.VT_BYREF) != 0) { vt &= ~VarEnum.VT_BYREF; m_nativeIndirections++; } // // Find the corresponding type and save it in result and store the custom attribute in m_attribute // Type result = null; m_attribute = null; switch (vt) { case VarEnum.VT_HRESULT: result = typeof(int); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Error); SetUnmanagedType(UnmanagedType.Error); break; case VarEnum.VT_VOID: result = typeof(void); break; case VarEnum.VT_UINT: result = typeof(uint); break; case VarEnum.VT_INT: result = typeof(int); break; case VarEnum.VT_UI1: result = typeof(byte); break; case VarEnum.VT_UI2: result = typeof(ushort); break; case VarEnum.VT_UI4: result = typeof(uint); break; case VarEnum.VT_UI8: result = typeof(ulong); break; case VarEnum.VT_I1: result = typeof(sbyte); break; case VarEnum.VT_I2: result = typeof(short); break; case VarEnum.VT_I4: result = typeof(int); break; case VarEnum.VT_I8: result = typeof(long); break; case VarEnum.VT_R4: result = typeof(float); break; case VarEnum.VT_R8: result = typeof(double); break; case VarEnum.VT_ERROR: result = typeof(int); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Error); SetUnmanagedType(UnmanagedType.Error); break; case VarEnum.VT_BSTR: result = typeof(string); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.BStr); SetUnmanagedType(UnmanagedType.BStr); // BSTR => string is special as BSTR are actually OLECHAR*, so we should add one indirection m_nativeIndirections++; break; case VarEnum.VT_DISPATCH: if (m_convertingNewEnumMember) { // When we are creating a new enum member, convert IDispatch to IEnumVariant TryUseCustomMarshaler(WellKnownGuids.IID_IEnumVARIANT, out result); } else { result = typeof(object); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.IDispatch); SetUnmanagedType(UnmanagedType.IDispatch); } // VT_DISPATCH => IDispatch * m_nativeIndirections++; break; case VarEnum.VT_UNKNOWN: if (m_convertingNewEnumMember) { // When we are creating a new enum member, convert IUnknown to IEnumVariant TryUseCustomMarshaler(WellKnownGuids.IID_IEnumVARIANT, out result); } else { result = typeof(object); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.IUnknown); SetUnmanagedType(UnmanagedType.IUnknown); } // VT_UNKNOWN => IUnknown * m_nativeIndirections++; break; case VarEnum.VT_LPSTR: result = typeof(string); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.LPStr); SetUnmanagedType(UnmanagedType.LPStr); m_nativeIndirections++; break; case VarEnum.VT_LPWSTR: result = typeof(string); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.LPWStr); SetUnmanagedType(UnmanagedType.LPWStr); m_nativeIndirections++; break; case VarEnum.VT_PTR: Debug.Assert(false, "Should not get here"); break; case VarEnum.VT_SAFEARRAY: { TypeDesc arrayDesc = m_typeDesc.lpadesc.tdescElem; VarEnum arrayVt = (VarEnum)arrayDesc.vt; Type userDefinedType = null; TypeConverter elemTypeConverter = new TypeConverter(m_info, m_typeInfo, arrayDesc, ConversionType.Element); Type elemType = elemTypeConverter.ConvertedType; // Determine the right VT for MarshalAs attribute bool pointerArray = false; if (arrayVt == VarEnum.VT_PTR) { arrayDesc = arrayDesc.lptdesc; arrayVt = (VarEnum)arrayDesc.vt; pointerArray = true; // We don't support marshalling pointers in array except UserType* & void* if (arrayVt != VarEnum.VT_USERDEFINED && arrayVt != VarEnum.VT_VOID) { arrayVt = VarEnum.VT_INT; m_conversionLoss = true; } } // // Emit UserDefinedSubType if necessary // if (arrayVt == VarEnum.VT_USERDEFINED) { if (elemType.IsEnum) { if (pointerArray) { arrayVt = VarEnum.VT_INT; m_conversionLoss = true; } else { // For enums, using VT_RECORD is better than VT_I4 // Within the runtime, if you specify VT_I4 for enums in SafeArray, we treat it the same way as VT_RECORD // Reflection API also accepts VT_RECORD instead of VT_I4 arrayVt = VarEnum.VT_RECORD; } } else if (elemType.IsValueType) { if (pointerArray) { arrayVt = VarEnum.VT_INT; m_conversionLoss = true; } else { arrayVt = VarEnum.VT_RECORD; } } else if (elemType.IsInterface) { if (pointerArray) { // decide VT_UNKNOWN / VT_DISPATCH if (InterfaceSupportsDispatch(elemType)) { arrayVt = VarEnum.VT_DISPATCH; } else { arrayVt = VarEnum.VT_UNKNOWN; } } else { arrayVt = VarEnum.VT_INT; m_conversionLoss = true; } } else if (elemType == typeof(object) && !elemTypeConverter.UseDefaultMarshal && (elemTypeConverter.UnmanagedType == UnmanagedType.IUnknown)) { // Special case for object that doesn't have default interface and will be marshalled as IUnknown arrayVt = VarEnum.VT_UNKNOWN; } userDefinedType = elemType; } m_conversionLoss |= elemTypeConverter.IsConversionLoss; // Transform to System.Array if /sysarray is set and not vararg if (((m_info.Settings.m_flags & TypeLibImporterFlags.SafeArrayAsSystemArray) != 0) && m_conversionType != ConversionType.VarArgParameter) { result = typeof(System.Array); } else { result = elemType.MakeArrayType(); // Don't need SafeArrayUserDefinedSubType for non System.Array case userDefinedType = null; } // TlbImp doesn't have this check for vt == VT_RECORD/VT_UNKNOWN/VT_DISPATCH therefore // it will emit SafeArrayUserDefinedSubType even it is not necessary/not valid // TlbImp2 will take this into account if ((userDefinedType != null) && (arrayVt == VarEnum.VT_RECORD || arrayVt == VarEnum.VT_UNKNOWN || arrayVt == VarEnum.VT_DISPATCH)) { // The name of the type would be full name in TlbImp2 m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsSafeArrayAndUserDefinedSubType(arrayVt, userDefinedType); } else { // Use I4 for enums when SafeArrayUserDefinedSubType is not specified if (elemType.IsEnum && arrayVt == VarEnum.VT_RECORD) { arrayVt = VarEnum.VT_I4; } m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsSafeArray(arrayVt); } SetUnmanagedType(UnmanagedType.SafeArray); // SafeArray <=> array is special because SafeArray is similar to Element* m_nativeIndirections++; break; } case VarEnum.VT_RECORD: case VarEnum.VT_USERDEFINED: { // Handle structs, interfaces, enums, and unions // Check if any ResolveTo Rule applied. TypeInfo refType = m_typeInfo.GetRefTypeInfo(m_typeDesc.hreftype); TypeAttr refAttr = refType.GetTypeAttr(); Type resolveToType; if (RuleEngineResolveRedirection(m_info.Settings.m_ruleSet, refType, out resolveToType)) { result = resolveToType; break; } // Support for aliasing TypeInfo realType; TypeAttr realAttr; ConvCommon.ResolveAlias(m_typeInfo, m_typeDesc, out realType, out realAttr); // Alias for a built-in type? if (realAttr.typekind == TypeLibTypes.Interop.TYPEKIND.TKIND_ALIAS) { // Recurse to convert the built-in type TypeConverter builtinType = new TypeConverter(m_info, realType, realAttr.tdescAlias, m_conversionType); result = builtinType.ConvertedType; m_attribute = builtinType.m_attribute; } else { // Otherwise, we must have a non-aliased type, and it is a user defined type // We should use the TypeInfo that this TypeDesc refers to realType = m_typeDesc.GetUserDefinedTypeInfo(m_typeInfo); TypeLibTypes.Interop.TYPEKIND typeKind = realAttr.typekind; using (realAttr = realType.GetTypeAttr()) { TypeLib typeLib = realType.GetContainingTypeLib(); // Convert StdOle2.Guid to System.Guid if (_IsStdOleGuid(realType)) { result = typeof(Guid); m_attribute = null; ResetUnmanagedType(); } else if (realAttr.Guid == WellKnownGuids.IID_IUnknown) { // Occasional goto makes sense // If VT_USERDEFINE *, and the VT_USERDEFINE is actually a VT_UNKNOWN => IUnknown *, we need to decrease the m_nativeIndirections // to compensate for the m_nativeIndirections++ in VT_UNKNOWN m_nativeIndirections--; goto case VarEnum.VT_UNKNOWN; } else if (realAttr.Guid == WellKnownGuids.IID_IDispatch) { // Occasional goto makes sense // See the IID_IUnknown case for why we need to -- m_nativeIndirections--; goto case VarEnum.VT_DISPATCH; } else { // Need to use CustomMarshaler? Type customMarshalerResultType; if (TryUseCustomMarshaler(realAttr.Guid, out customMarshalerResultType)) { result = customMarshalerResultType; } else { IConvBase ret = m_info.GetTypeRef(ConvCommon.TypeKindToConvType(typeKind), realType); if (m_conversionType == ConversionType.Field) { // Too bad. Reflection API requires that the field type must be created before creating // the struct/union type // Only process indirection = 0 case because > 1 case will be converted to IntPtr // Otherwise it will leads to a infinite recursion, if you consider the following scenario: // struct A // { // struct B // { // struct A *a; // } b; // } if (ret is ConvUnionLocal && m_nativeIndirections == 0) { ConvUnionLocal convUnion = ret as ConvUnionLocal; convUnion.Create(); } else if (ret is ConvStructLocal && m_nativeIndirections == 0) { ConvStructLocal convStruct = ret as ConvStructLocal; convStruct.Create(); } else if (ret is ConvEnumLocal && m_nativeIndirections == 0) { ConvEnumLocal convEnum = ret as ConvEnumLocal; convEnum.Create(); } } result = ret.ManagedType; // Don't reply on result.IsInterface as we have some weird scenarios like refering to a exported type lib // which has interfaces that are class interfaces and have the same name as a class. // For example, manage class M has a class interface _M, and their managed name are both M if (ret.ConvType == ConvType.Interface || ret.ConvType == ConvType.EventInterface || ret.ConvType == ConvType.ClassInterface) { m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Interface); SetUnmanagedType(UnmanagedType.Interface); } if (ret.ConvType == ConvType.CoClass) { // We need to convert CoClass to default interface (could be converted to class interface if it is exclusive) in signatures Debug.Assert(ret is IConvCoClass); IConvCoClass convCoClass = ret as IConvCoClass; if (convCoClass.DefaultInterface != null) { // Use the default interface result = convCoClass.DefaultInterface.ManagedType; m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Interface); SetUnmanagedType(UnmanagedType.Interface); } else { // The coclass has no default interface (source interface excluded) // Marshal it as IUnknown result = typeof(object); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.IUnknown); SetUnmanagedType(UnmanagedType.IUnknown); } } } } } } } break; case VarEnum.VT_VARIANT: result = typeof(object); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Struct); SetUnmanagedType(UnmanagedType.Struct); // object is special that it will be marshaled to VARIANT // because we'll think object as having one indirection, now we are one indirection less, // so we need add 1 to m_indirections m_nativeIndirections++; break; case VarEnum.VT_CY: result = typeof(System.Decimal); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.Currency); SetUnmanagedType(UnmanagedType.Currency); break; case VarEnum.VT_DATE: result = typeof(System.DateTime); break; case VarEnum.VT_DECIMAL: result = typeof(System.Decimal); break; case VarEnum.VT_CARRAY: { TypeDesc elemTypeDesc = m_typeDesc.lptdesc; TypeConverter elemTypeConverter = new TypeConverter(m_info, m_typeInfo, elemTypeDesc, ConversionType.Element); Type elemType = elemTypeConverter.ConvertedType; result = elemType.MakeArrayType(); m_conversionLoss |= elemTypeConverter.IsConversionLoss; uint elements = 1; SAFEARRAYBOUND[] bounds = m_typeDesc.lpadesc.Bounds; foreach (SAFEARRAYBOUND bound in bounds) { elements *= bound.cElements; } // SizeConst can only hold Int32.MaxValue if (elements <= Int32.MaxValue) { UnmanagedType arrayType; if (m_conversionType == ConversionType.Field) { arrayType = UnmanagedType.ByValArray; } else { arrayType = UnmanagedType.LPArray; } if (elemTypeConverter.UseDefaultMarshal) { m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsConstArray(arrayType, (int)elements); } else { if (elemTypeConverter.UnmanagedType == UnmanagedType.BStr || elemTypeConverter.UnmanagedType == UnmanagedType.LPStr || elemTypeConverter.UnmanagedType == UnmanagedType.LPWStr || elemTypeConverter.UnmanagedType == UnmanagedType.VariantBool) { m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsConstArray(arrayType, (int)elements, elemTypeConverter.UnmanagedType); } else { m_attribute = CustomAttributeHelper.GetBuilderForMarshalAsConstArray(arrayType, (int)elements); } } SetUnmanagedType(arrayType); } else { m_nativeIndirections = 0; result = typeof(IntPtr); m_attribute = null; ResetUnmanagedType(); m_conversionLoss = true; } } break; case VarEnum.VT_BOOL: // For VT_BOOL in fields, use short if v2 switch is not specified. if (m_conversionType == ConversionType.Field) { if (m_info.Settings.m_isVersion2) { result = typeof(bool); m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.VariantBool); SetUnmanagedType(UnmanagedType.VariantBool); } else { result = typeof(short); } } else { result = typeof(bool); SetUnmanagedType(UnmanagedType.VariantBool); } break; default: m_info.ReportEvent( WarningCode.Wrn_BadVtType, Resource.FormatString("Wrn_BadVtType", (int)vt, m_typeInfo.GetDocumentation())); result = typeof(IntPtr); m_conversionLoss = true; break; } // // String -> StringBuilder special case // if (result == typeof(string)) { if (_IsParamOut() && m_nativeIndirections == 1 && (m_conversionType == ConversionType.Parameter || m_conversionType == ConversionType.VarArgParameter)) { // [out] or [in, out] LPSTR/LPWSTR scenario if (vt != VarEnum.VT_BSTR) { // String is immutable and cannot be [out]/[in, out]. We can convert to StringBuilder result = typeof(StringBuilder); } else // VT_BSTR { // VT_BSTR is also immutable. So conversion loss here m_conversionLoss = true; result = typeof(IntPtr); m_attribute = null; m_nativeIndirections = 0; ResetUnmanagedType(); } } } // Special rule for void* => IntPtr if (result == typeof(void)) { result = typeof(IntPtr); switch (m_conversionType) { case ConversionType.Element: m_nativeIndirections = 0; break; case ConversionType.Field: m_nativeIndirections = 0; break; default: if (m_nativeIndirections > 1) { m_nativeIndirections = 1; } else { m_nativeIndirections = 0; } break; } } // // If the type is already a byref type, remove the byref and add extra indirection(s). // This is necessary to avoid trying to call MakeByRef on the byref type // if (result.IsByRef) { result = result.GetElementType(); if (result.IsValueType) { m_nativeIndirections++; // Value& = Value * } else { m_nativeIndirections += 2; // RefType& = RefType** } } // // Process indirection // if (m_nativeIndirections > 0) { if (result.IsValueType) { switch (m_conversionType) { case ConversionType.VarArgParameter: case ConversionType.Parameter: // Decimal/Guid can support extra level of indirection using LpStruct in parameters // LpStruct has no effect in other places and for other types // Only use LpStruct for scenarios like GUID ** // This is different from old TlbImp. Old TlbImp will use IntPtr if ((result == typeof(Decimal) || result == typeof(Guid)) && m_nativeIndirections == 2) { m_nativeIndirections--; m_attribute = CustomAttributeHelper.GetBuilderForMarshalAs(UnmanagedType.LPStruct); ResetUnmanagedType(); SetUnmanagedType(UnmanagedType.LPStruct); } if (m_nativeIndirections >= 2) { m_conversionLoss = true; result = typeof(IntPtr); m_attribute = null; ResetUnmanagedType(); } else if (m_nativeIndirections > 0) { result = result.MakeByRefType(); } break; case ConversionType.Field: m_conversionLoss = true; result = typeof(IntPtr); m_attribute = null; ResetUnmanagedType(); break; case ConversionType.ParamRetVal: m_nativeIndirections--; goto case ConversionType.ReturnValue; // Fall through to ConversionType.ReturnValue case ConversionType.ReturnValue: if (m_nativeIndirections >= 1) { m_conversionLoss = true; result = typeof(IntPtr); m_attribute = null; ResetUnmanagedType(); } break; case ConversionType.Element: m_conversionLoss = true; result = typeof(IntPtr); m_attribute = null; ResetUnmanagedType(); break; } } else { switch (m_conversionType) { case ConversionType.Field: // ** => IntPtr, ConversionLoss if (m_nativeIndirections > 1) { result = typeof(IntPtr); m_conversionLoss = true; m_attribute = null; ResetUnmanagedType(); } break; case ConversionType.VarArgParameter: case ConversionType.Parameter: if (m_nativeIndirections > 2) { result = typeof(IntPtr); m_conversionLoss = true; m_attribute = null; ResetUnmanagedType(); } else if (m_nativeIndirections == 2) { result = result.MakeByRefType(); } break; case ConversionType.ParamRetVal: m_nativeIndirections--; goto case ConversionType.ReturnValue; // Fall through to ConversionType.ReturnValue case ConversionType.ReturnValue: if (m_nativeIndirections > 1) { result = typeof(IntPtr); m_conversionLoss = true; m_attribute = null; ResetUnmanagedType(); } break; case ConversionType.Element: if (m_nativeIndirections > 1) { m_conversionLoss = true; result = typeof(IntPtr); m_attribute = null; ResetUnmanagedType(); } break; } } } m_convertedType = result; }
/// <summary> /// Create the event interface /// </summary> public override void OnCreate() { if (m_type != null) { return; } string name = m_convInterface.ManagedName; m_convInterface.Create(); using (TypeAttr attr = m_convInterface.RefTypeInfo.GetTypeAttr()) { // // Emit attributes // // // Emit [ComEventInterfaceAttribute(...)] // ConstructorInfo ctorComEventInterface = typeof(ComEventInterfaceAttribute).GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(Type), typeof(Type) }, null); // // Build the blob manually before creating the event interface / provider types. // We only need to give the name of the types, in order to simplify creation logic and avoid dependency // CustomAttributeBlobBuilder blobBuilder = new CustomAttributeBlobBuilder(); string eventInterfaceFullyQualifiedName = name; if (m_convInterface.ConvScope == ConvScope.External) { eventInterfaceFullyQualifiedName = m_convInterface.ManagedType.AssemblyQualifiedName; } blobBuilder.AddFixedArg(eventInterfaceFullyQualifiedName); // source interface // Handle event provider name generation collision scenario m_eventProviderName = m_info.GetUniqueManagedName( m_info.GetRecommendedManagedName(m_convInterface.RefTypeInfo, ConvType.Interface, true) + "_EventProvider"); blobBuilder.AddFixedArg(m_eventProviderName); // corresponding event provider m_typeBuilder.SetCustomAttribute(ctorComEventInterface, blobBuilder.GetBlob()); // // Emit ComVisibleAttribute(false) // m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComVisible(false)); // // Emit TypeLibTypeAttribute for TYPEFLAG_FHIDDEN // m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType(TypeLibTypeFlags.FHidden)); bool isConversionLoss = false; // // Verify if the type has any properties // Type interfaceType = m_convInterface.RealManagedType; if (interfaceType.GetProperties().Length > 0) { // Emit a warning and we'll skip the properties m_info.ReportEvent( WarningCode.Wrn_NoPropsInEvents, Resource.FormatString("Wrn_NoPropsInEvents", RefTypeInfo.GetDocumentation())); isConversionLoss = true; } // // Create event interface // InterfaceInfo eventInterfaceInfo = new InterfaceInfo(m_info, m_typeBuilder, false, m_convInterface.RefTypeInfo, attr, false, true); ConvCommon.CreateEventInterfaceCommon(eventInterfaceInfo); isConversionLoss |= eventInterfaceInfo.IsConversionLoss; // // Emit ComConversionLossAttribute if necessary // if (eventInterfaceInfo.IsConversionLoss) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); } } m_type = m_typeBuilder.CreateType(); }
protected override void OnDefineType() { string classInterfaceName = m_info.GetUniqueManagedName(m_coclassTypeInfo, ConvType.ClassInterface); Type defaultInterfaceType = null; Type defaultSourceInterfaceType = null; m_convInterface = null; m_convSourceInterface = null; // // Convert default interface // if (m_defaultInterfaceTypeInfo != null) { m_convInterface = (IConvInterface)m_info.GetTypeRef(ConvType.Interface, m_defaultInterfaceTypeInfo); // Don't create the interface because we haven't associated the default interface with the class interface yet // We don't want to create anything in the "Define" stage //m_convInterface.Create(); defaultInterfaceType = m_convInterface.ManagedType; } // // Convert default source interface // if (m_defaultSourceInterfaceTypeInfo != null) { m_convSourceInterface = (IConvInterface)m_info.GetTypeRef(ConvType.Interface, m_defaultSourceInterfaceTypeInfo); // Don't create the interface because we haven't associated the default interface with the class interface yet // We don't want to create anything in the "Define" stage // m_convSourceInterface.Create(); Type sourceInterfaceType = m_convSourceInterface.RealManagedType; IConvEventInterface convEventInterface = m_convSourceInterface.DefineEventInterface(); // Don't create the interface because we haven't associated the default interface with the class interface yet // We don't want to create anything in the "Define" stage // convEventInterface.Create(); defaultSourceInterfaceType = m_convSourceInterface.EventInterface.ManagedType; } // // Prepare list of implemented interfaces // List <Type> implTypes = new List <Type>(); if (defaultInterfaceType != null) { implTypes.Add(defaultInterfaceType); } if (defaultSourceInterfaceType != null) { implTypes.Add(defaultSourceInterfaceType); } // Create the class interface m_typeBuilder = m_info.ModuleBuilder.DefineType( classInterfaceName, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract | TypeAttributes.Import, null, implTypes.ToArray()); // Link to it so that ManagedType will return the class interface while GetWrappedInterfaceType will return the // real interface // This must be done before creating the coclass because coclass needs this information // Only do so when the default interface is exclusively belongs to one coclass if (m_convInterface != null && m_isExclusive) { m_convInterface.AssociateWithExclusiveClassInterface(this as IConvClassInterface); } // Emit GuidAttribute, which is the same as the default interface, if it exists if (defaultInterfaceType != null) { ConvCommon.DefineGuid(m_convInterface.RefTypeInfo, m_convInterface.RefNonAliasedTypeInfo, m_typeBuilder); } // Make sure we know about the class interface before we go to define the coclass in the next statement m_info.RegisterType(m_typeBuilder, this); m_info.AddToSymbolTable(m_coclassTypeInfo, ConvType.ClassInterface, this); // Handle [CoClass(typeof(...))] Type typeRefCoClass = m_info.GetTypeRef(ConvType.CoClass, m_coclassTypeInfo).ManagedType; m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForCoClass(typeRefCoClass)); }
/// <summary> /// Create the type for coclass /// </summary> public override void OnCreate() { // // Avoid duplicate creation // if (m_type != null) { return; } // // Create constructor // This is created before creating other methods because if anything fails, the constructor would still be valid // Otherwise reflection API will try to create one for us which will have incorrect setting (such as no internalcall flag) CreateConstructor(); bool isConversionLoss = false; TypeInfo typeInfo = RefNonAliasedTypeInfo; if ((m_info.Settings.m_flags & TypeLibImporterFlags.PreventClassMembers) == 0) { using (TypeAttr attr = typeInfo.GetTypeAttr()) { Dictionary <Guid, bool> processedInterfaces = new Dictionary <Guid, bool>(); // Iterate through every interface and override the methods // Process the default interface first for (int m = 0; m < 2; ++m) { int nCount = attr.cImplTypes; for (int n = 0; n < nCount; ++n) { IMPLTYPEFLAGS flags = typeInfo.GetImplTypeFlags(n); bool bDefault = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) != 0; bool bSource = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0; // Use exclusive or to process just the default interface on the first pass if (bDefault ^ m == 1) { TypeInfo typeImpl = typeInfo.GetRefType(n); using (TypeAttr attrImpl = typeImpl.GetTypeAttr()) { if (attrImpl.Guid == WellKnownGuids.IID_IUnknown || attrImpl.Guid == WellKnownGuids.IID_IDispatch) { continue; } // Skip non-dispatch interfaces that doesn't derive from IUnknown if (!attrImpl.IsDispatch && !ConvCommon.IsDerivedFromIUnknown(typeImpl)) { continue; } // Skip duplicate interfaces in type library // In .IDL you can actually write: // coclass A // { // interface IA; // interface IA; // ... // } // if (!processedInterfaces.ContainsKey(attrImpl.Guid)) { HandleParentInterface(typeImpl, bSource, ref isConversionLoss, bDefault); processedInterfaces.Add(attrImpl.Guid, true); } } } } } } } // // Emit ComConversionLoss attribute if necessary // if (isConversionLoss) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComConversionLoss()); } m_type = m_typeBuilder.CreateType(); }
protected override void OnDefineType() { TypeInfo typeInfo = RefNonAliasedTypeInfo; using (TypeAttr attr = typeInfo.GetTypeAttr()) { string name = m_info.GetUniqueManagedName(RefTypeInfo, ConvType.CoClass); // // Collect information for a list of interfaces & event interface types // List <Type> intfList = new List <Type>(); // interface list List <Type> eventIntfList = new List <Type>(); // event interface list TypeInfo defaultInterfaceTypeInfo = null; int nCount = attr.cImplTypes; string sourceInterfaceNames = String.Empty; bool hasDefaultInterface = false; bool implementsIEnumerable = ConvCommon.ExplicitlyImplementsIEnumerable(typeInfo, attr); for (int n = 0; n < nCount; ++n) { IMPLTYPEFLAGS flags = typeInfo.GetImplTypeFlags(n); bool isDefault = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FDEFAULT) != 0; bool isSource = (flags & IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) != 0; TypeInfo typeImpl = typeInfo.GetRefType(n); using (TypeAttr attrImpl = typeImpl.GetTypeAttr()) { // Skip IUnknown & IDispatch if (attrImpl.Guid == WellKnownGuids.IID_IDispatch || attrImpl.Guid == WellKnownGuids.IID_IUnknown) { continue; } // Skip non-dispatch interfaces that doesn't derive from IUnknown if (!attrImpl.IsDispatch && !ConvCommon.IsDerivedFromIUnknown(typeImpl)) { continue; } IConvInterface convInterface = (IConvInterface)m_info.GetTypeRef(ConvType.Interface, typeImpl); // For source interfaces, try create the event interface // Could be already created if it is the default source interface if (isSource) { convInterface.DefineEventInterface(); } // Use the RealManagedType (avoid getting the class interface) Type typeRef = convInterface.RealManagedType; // Append the source interface name to the list for the ComSourceInterfacesAttribute if (isSource) { string interfaceName; if (convInterface.ConvScope == ConvScope.External) { interfaceName = typeRef.AssemblyQualifiedName + "\0"; } else { interfaceName = typeRef.FullName + "\0"; } // Insert default source interface to the beginning if (isDefault) { sourceInterfaceNames = interfaceName + sourceInterfaceNames; } else { sourceInterfaceNames = sourceInterfaceNames + interfaceName; } } if (isDefault) { // Add the real interface first if (isSource) { // For source interface, use the event interface instead // Insert to the beginning eventIntfList.Insert(0, convInterface.EventInterface.ManagedType); } else { m_defaultInterface = convInterface; // Insert to the beginning intfList.Insert(0, typeRef); hasDefaultInterface = true; defaultInterfaceTypeInfo = typeImpl; } } else { if (isSource) { // For source interface, add the event interface instead eventIntfList.Add(convInterface.EventInterface.ManagedType); } else { if (m_defaultInterface == null) { m_defaultInterface = convInterface; defaultInterfaceTypeInfo = typeImpl; } intfList.Add(typeRef); } } } } // // Get class interface // m_classInterface = m_info.GetTypeRef(ConvType.ClassInterface, RefTypeInfo) as IConvClassInterface; if (m_classInterface == null) { throw new TlbImpInvalidTypeConversionException(RefTypeInfo); } // // Build implemented type list in a specific order // List <Type> implTypeList = new List <Type>(); if (hasDefaultInterface) { implTypeList.Add(intfList[0]); intfList.RemoveAt(0); implTypeList.Add(m_classInterface.ManagedType); } else { implTypeList.Add(m_classInterface.ManagedType); if (intfList.Count > 0) { implTypeList.Add(intfList[0]); intfList.RemoveAt(0); } } if (eventIntfList.Count > 0) { implTypeList.Add(eventIntfList[0]); eventIntfList.RemoveAt(0); } implTypeList.AddRange(intfList); implTypeList.AddRange(eventIntfList); // Check to see if the default interface has a member with a DISPID of DISPID_NEWENUM. if (defaultInterfaceTypeInfo != null) { if (!implementsIEnumerable && ConvCommon.HasNewEnumMember(m_info, defaultInterfaceTypeInfo)) { implTypeList.Add(typeof(System.Collections.IEnumerable)); } } // Check to see if the IEnumerable Custom Value exists on the CoClass if doesn't inherit from IEnumerable yet if (!implTypeList.Contains(typeof(System.Collections.IEnumerable))) { if (ConvCommon.HasForceIEnumerableCustomAttribute(typeInfo)) { implTypeList.Add(typeof(System.Collections.IEnumerable)); } } // Define the type m_typeBuilder = m_info.ModuleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Import, typeof(Object), implTypeList.ToArray()); // Handle [Guid(...)] custom attribute ConvCommon.DefineGuid(RefTypeInfo, RefNonAliasedTypeInfo, m_typeBuilder); // Handle [ClassInterface(ClassInterfaceType.None)] m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForClassInterface(ClassInterfaceType.None)); // Handle [TypeLibType(...)] if evaluate to non-0 using (TypeAttr refTypeAttr = RefTypeInfo.GetTypeAttr()) { if (refTypeAttr.wTypeFlags != 0) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForTypeLibType((TypeLibTypeFlags)refTypeAttr.wTypeFlags)); } } // Handle [ComSourceInterfacesAttribute] if (sourceInterfaceNames != String.Empty) { sourceInterfaceNames += "\0"; m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForComSourceInterfaces(sourceInterfaceNames)); } // Add to symbol table automatically m_info.AddToSymbolTable(RefTypeInfo, ConvType.CoClass, this); // Register type m_info.RegisterType(m_typeBuilder, this); } }
protected void DefineType(ConverterInfo info, TypeInfo typeInfo, bool dealWithAlias) { m_info = info; m_typeInfo = typeInfo; if (dealWithAlias) { m_nonAliasedTypeInfo = ConvCommon.GetAlias(typeInfo); } else { m_nonAliasedTypeInfo = typeInfo; } try { OnDefineType(); // // Emit SuppressUnmanagedCodeSecurityAttribute for /unsafe switch // if ((m_info.Settings.m_flags & TypeLibImporterFlags.UnsafeInterfaces) != 0) { if (ConvType != ConvType.ClassInterface && ConvType != ConvType.EventInterface) { m_typeBuilder.SetCustomAttribute(CustomAttributeHelper.GetBuilderForSuppressUnmanagedCodeSecurity()); } } // Rule Engine AddAttributeAction if (m_info.Settings.m_ruleSet != null) { ICategory category = TypeCategory.GetInstance(); TypeInfoMatchTarget target = null; using (TypeAttr attr = m_typeInfo.GetTypeAttr()) { TypeLibTypes.Interop.TYPEKIND kind = attr.typekind; target = new TypeInfoMatchTarget(m_typeInfo.GetContainingTypeLib(), m_typeInfo, kind); } AbstractActionManager actionManager = RuleEngine.GetActionManager(); List <Rule> addAttributeRules = m_info.Settings.m_ruleSet.GetRule( category, AddAttributeActionDef.GetInstance(), target); foreach (Rule rule in addAttributeRules) { AddAttributeAction addAttributeAction = rule.Action as AddAttributeAction; ConstructorInfo attributeCtor; byte[] blob; bool success = true; if (addAttributeAction.GetCustomAttribute(out attributeCtor, out blob)) { try { m_typeBuilder.SetCustomAttribute(attributeCtor, blob); } catch (Exception) { success = false; } } else { success = false; } if (!success) { string name = m_typeInfo.GetDocumentation(); string msg = Resource.FormatString("Wrn_AddCustomAttributeFailed", addAttributeAction.TypeName, name); m_info.ReportEvent(WarningCode.Wrn_AddCustomAttributeFailed, msg); } } } } catch (ReflectionTypeLoadException) { throw; // Fatal failure. Throw } catch (TlbImpResolveRefFailWrapperException) { throw; // Fatal failure. Throw } catch (TlbImpGeneralException) { throw; // Fatal failure. Throw } catch (Exception) { string name = String.Empty; if (m_typeInfo != null) { try { name = m_typeInfo.GetDocumentation(); } catch (Exception) { } } if (name != String.Empty) { string msg = Resource.FormatString("Wrn_InvalidTypeInfo", name); m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo, msg); } else { string msg = Resource.FormatString("Wrn_InvalidTypeInfo_Unnamed"); m_info.ReportEvent(WarningCode.Wrn_InvalidTypeInfo_Unnamed, msg); } // When failure, try to create the type anyway if (m_typeBuilder != null) { m_type = m_typeBuilder.CreateType(); } } }