diff --git a/reflect/CustomAttributeData.cs b/reflect/CustomAttributeData.cs index 79c009f8..5cd17d52 100644 --- a/reflect/CustomAttributeData.cs +++ b/reflect/CustomAttributeData.cs @@ -46,7 +46,7 @@ namespace IKVM.Reflection this.index = index; } - // this is for pseudo-custom attributes + // this is for pseudo-custom attributes and CustomAttributeBuilder.ToData() internal CustomAttributeData(Module module, ConstructorInfo constructor, object[] args, List namedArguments) { this.module = module; @@ -148,11 +148,11 @@ namespace IKVM.Reflection ConstructorInfo constructor; if (type == u.System_Security_Permissions_HostProtectionAttribute && action == (int)System.Security.Permissions.SecurityAction.LinkDemand) { - constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); + constructor = type.GetPseudoCustomAttributeConstructor(); } else { - constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { u.System_Security_Permissions_SecurityAction }, null); + constructor = type.GetPseudoCustomAttributeConstructor(u.System_Security_Permissions_SecurityAction); } // LAMESPEC there is an additional length here (probably of the named argument list) ByteReader slice = br.Slice(br.ReadCompressedInt()); diff --git a/reflect/MarshalSpec.cs b/reflect/MarshalSpec.cs index 9c326c68..4f0db8de 100644 --- a/reflect/MarshalSpec.cs +++ b/reflect/MarshalSpec.cs @@ -1,5 +1,5 @@ /* - Copyright (C) 2008, 2010 Jeroen Frijters + Copyright (C) 2008-2011 Jeroen Frijters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -112,7 +112,31 @@ namespace IKVM.Reflection blob.ReadCompressedInt(); marshalType = ReadString(blob); marshalCookie = ReadString(blob); - marshalTypeRef = module.Assembly.GetType(marshalType) ?? module.universe.GetType(marshalType); + + // we have to use a custom type lookup scheme here, because we want to use FindType to avoid a MissingAssemblyException + TypeNameParser parser = TypeNameParser.Parse(marshalType, false); + if (!parser.Error) + { + TypeName n = TypeName.Split(parser.FirstNamePart); + Type type = null; + if (parser.AssemblyName != null) + { + Assembly asm = module.Assembly.universe.Load(parser.AssemblyName, module.Assembly, false); + if (asm != null) + { + type = asm.FindType(n); + } + } + else + { + type = module.Assembly.FindType(n) + ?? module.universe.Mscorlib.FindType(n); + } + if (type != null) + { + marshalTypeRef = parser.Expand(type, module.Assembly, false, marshalType); + } + } } Type typeofMarshalAs = module.universe.System_Runtime_InteropServices_MarshalAsAttribute; @@ -122,47 +146,57 @@ namespace IKVM.Reflection List named = new List(); if (arraySubType != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("ArraySubType"), new CustomAttributeTypedArgument(typeofUnmanagedType, arraySubType.Value))); + AddNamedArgument(named, typeofMarshalAs, "ArraySubType", typeofUnmanagedType, arraySubType.Value); } if (sizeParamIndex != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SizeParamIndex"), new CustomAttributeTypedArgument(module.universe.System_Int16, sizeParamIndex.Value))); + AddNamedArgument(named, typeofMarshalAs, "SizeParamIndex", module.universe.System_Int16, sizeParamIndex.Value); } if (sizeConst != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SizeConst"), new CustomAttributeTypedArgument(module.universe.System_Int32, sizeConst.Value))); + AddNamedArgument(named, typeofMarshalAs, "SizeConst", module.universe.System_Int32, sizeConst.Value); } if (safeArraySubType != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SafeArraySubType"), new CustomAttributeTypedArgument(typeofVarEnum, safeArraySubType.Value))); + AddNamedArgument(named, typeofMarshalAs, "SafeArraySubType", typeofVarEnum, safeArraySubType.Value); } if (safeArrayUserDefinedSubType != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("SafeArrayUserDefinedSubType"), new CustomAttributeTypedArgument(typeofType, safeArrayUserDefinedSubType))); + AddNamedArgument(named, typeofMarshalAs, "SafeArrayUserDefinedSubType", typeofType, safeArrayUserDefinedSubType); } if (iidParameterIndex != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("IidParameterIndex"), new CustomAttributeTypedArgument(module.universe.System_Int32, iidParameterIndex.Value))); + AddNamedArgument(named, typeofMarshalAs, "IidParameterIndex", module.universe.System_Int32, iidParameterIndex.Value); } if (marshalType != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalType"), new CustomAttributeTypedArgument(module.universe.System_String, marshalType))); + AddNamedArgument(named, typeofMarshalAs, "MarshalType", module.universe.System_String, marshalType); } if (marshalTypeRef != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalTypeRef"), new CustomAttributeTypedArgument(module.universe.System_Type, marshalTypeRef))); + AddNamedArgument(named, typeofMarshalAs, "MarshalTypeRef", module.universe.System_Type, marshalTypeRef); } if (marshalCookie != null) { - named.Add(new CustomAttributeNamedArgument(typeofMarshalAs.GetField("MarshalCookie"), new CustomAttributeTypedArgument(module.universe.System_String, marshalCookie))); + AddNamedArgument(named, typeofMarshalAs, "MarshalCookie", module.universe.System_String, marshalCookie); } - ConstructorInfo constructor = typeofMarshalAs.GetConstructor(new Type[] { typeofUnmanagedType }); + ConstructorInfo constructor = typeofMarshalAs.GetPseudoCustomAttributeConstructor(typeofUnmanagedType); return new CustomAttributeData(module, constructor, new object[] { unmanagedType }, named); } } throw new BadImageFormatException(); } + private static void AddNamedArgument(List list, Type attributeType, string fieldName, Type valueType, object value) + { + // some fields are not available on the .NET Compact Framework version of MarshalAsAttribute + FieldInfo field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, null, null)); + if (field != null) + { + list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value))); + } + } + internal static void SetMarshalAsAttribute(ModuleBuilder module, int token, CustomAttributeBuilder attribute) { attribute = attribute.DecodeBlob(module.Assembly); diff --git a/reflect/Reader/Field.cs b/reflect/Reader/Field.cs index 92eb2c78..df489b47 100644 --- a/reflect/Reader/Field.cs +++ b/reflect/Reader/Field.cs @@ -128,7 +128,7 @@ namespace IKVM.Reflection.Reader { if (module.FieldLayout.records[i].Field == rid) { - ConstructorInfo constructor = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute.GetConstructor(new Type[] { module.universe.System_Int32 }); + ConstructorInfo constructor = module.universe.System_Runtime_InteropServices_FieldOffsetAttribute.GetPseudoCustomAttributeConstructor(module.universe.System_Int32); list.Add(new CustomAttributeData(module, constructor, new object[] { module.FieldLayout.records[i].Offset }, null)); diff --git a/reflect/Reader/Method.cs b/reflect/Reader/Method.cs index 9c1d7278..2dfb8614 100644 --- a/reflect/Reader/Method.cs +++ b/reflect/Reader/Method.cs @@ -266,7 +266,7 @@ namespace IKVM.Reflection.Reader const short CharMapErrorOff = 0x2000; Type type = module.universe.System_Runtime_InteropServices_DllImportAttribute; - ConstructorInfo constructor = type.GetConstructor(new Type[] { module.universe.System_String }); + ConstructorInfo constructor = type.GetPseudoCustomAttributeConstructor(module.universe.System_String); List list = new List(); int flags = module.ImplMap.records[i].MappingFlags; string entryPoint = module.GetString(module.ImplMap.records[i].ImportName); @@ -312,10 +312,10 @@ namespace IKVM.Reflection.Reader AddNamedArgument(list, type, "ExactSpelling", flags, NoMangle); AddNamedArgument(list, type, "SetLastError", flags, SupportsLastError); AddNamedArgument(list, type, "PreserveSig", (int)GetMethodImplementationFlags(), (int)MethodImplAttributes.PreserveSig); - AddNamedArgument(list, type, "CallingConvention", (int)callingConvention); + AddNamedArgument(list, type, "CallingConvention", module.universe.System_Runtime_InteropServices_CallingConvention, (int)callingConvention); if (charSet.HasValue) { - AddNamedArgument(list, type, "CharSet", (int)charSet.Value); + AddNamedArgument(list, type, "CharSet", module.universe.System_Runtime_InteropServices_CharSet, (int)charSet.Value); } if ((flags & (BestFitOn | BestFitOff)) != 0) { @@ -349,7 +349,7 @@ namespace IKVM.Reflection.Reader private static void AddNamedArgument(List list, Type attributeType, string fieldName, Type valueType, object value) { // some fields are not available on the .NET Compact Framework version of DllImportAttribute - FieldInfo field = attributeType.GetField(fieldName); + FieldInfo field = attributeType.FindField(fieldName, FieldSignature.Create(valueType, null, null)); if (field != null) { list.Add(new CustomAttributeNamedArgument(field, new CustomAttributeTypedArgument(valueType, value))); diff --git a/reflect/Type.cs b/reflect/Type.cs index 2f5b5009..6d58cb20 100644 --- a/reflect/Type.cs +++ b/reflect/Type.cs @@ -1636,6 +1636,16 @@ namespace IKVM.Reflection typeFlags |= TypeFlags.ValueType; return this; } + + internal ConstructorInfo GetPseudoCustomAttributeConstructor(params Type[] parameterTypes) + { + Universe u = this.Module.universe; + MethodSignature methodSig = MethodSignature.MakeFromBuilder(u.System_Void, parameterTypes, null, CallingConventions.Standard | CallingConventions.HasThis, 0); + MethodBase mb = + FindMethod(".ctor", methodSig) ?? + u.GetMissingMethodOrThrow(this, ".ctor", methodSig); + return (ConstructorInfo)mb; + } } abstract class ElementHolderType : Type diff --git a/reflect/Universe.cs b/reflect/Universe.cs index 2b090444..4c9a0a97 100644 --- a/reflect/Universe.cs +++ b/reflect/Universe.cs @@ -125,6 +125,8 @@ namespace IKVM.Reflection private Type typeof_System_Runtime_InteropServices_StructLayoutAttribute; private Type typeof_System_Runtime_InteropServices_OptionalAttribute; private Type typeof_System_Runtime_InteropServices_PreserveSigAttribute; + private Type typeof_System_Runtime_InteropServices_CallingConvention; + private Type typeof_System_Runtime_InteropServices_CharSet; private Type typeof_System_Runtime_InteropServices_ComImportAttribute; private Type typeof_System_Runtime_CompilerServices_DecimalConstantAttribute; private Type typeof_System_Runtime_CompilerServices_SpecialNameAttribute; @@ -371,6 +373,16 @@ namespace IKVM.Reflection get { return typeof_System_Runtime_InteropServices_PreserveSigAttribute ?? (typeof_System_Runtime_InteropServices_PreserveSigAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.PreserveSigAttribute))); } } + internal Type System_Runtime_InteropServices_CallingConvention + { + get { return typeof_System_Runtime_InteropServices_CallingConvention ?? (typeof_System_Runtime_InteropServices_CallingConvention = ImportMscorlibType(typeof(System.Runtime.InteropServices.CallingConvention))); } + } + + internal Type System_Runtime_InteropServices_CharSet + { + get { return typeof_System_Runtime_InteropServices_CharSet ?? (typeof_System_Runtime_InteropServices_CharSet = ImportMscorlibType(typeof(System.Runtime.InteropServices.CharSet))); } + } + internal Type System_Runtime_InteropServices_ComImportAttribute { get { return typeof_System_Runtime_InteropServices_ComImportAttribute ?? (typeof_System_Runtime_InteropServices_ComImportAttribute = ImportMscorlibType(typeof(System.Runtime.InteropServices.ComImportAttribute))); }