X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.Reflection.Emit%2FAssemblyBuilder.cs;h=5f49190abb1e28f7fbb91d1bd02a26c4c71d16e3;hb=907cba59ec02620c0a7cf08b49e8305f4cacad16;hp=1149eddbc24738439dd6bb85a0d1afbe81310b11;hpb=dfad48f3447511fabd98c74376bcca06bb251392;p=mono.git diff --git a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs index 1149eddbc24..5f49190abb1 100644 --- a/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs +++ b/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs @@ -39,6 +39,7 @@ using System.Runtime.Serialization; using System.Globalization; using System.Runtime.CompilerServices; using System.Collections; +using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; @@ -90,10 +91,121 @@ namespace System.Reflection.Emit } } -#if NET_2_0 + internal class GenericInstanceKey { + Type gtd; + internal Type[] args; + int hash_code; + + internal GenericInstanceKey (Type gtd, Type[] args) + { + this.gtd = gtd; + this.args = args; + + hash_code = gtd.GetHashCode (); + for (int i = 0; i < args.Length; ++i) + hash_code ^= args [i].GetHashCode (); + } + + static bool IsBoundedVector (Type type) { + ArrayType at = type as ArrayType; + if (at != null) + return at.GetEffectiveRank () == 1; + return type.ToString ().EndsWith ("[*]", StringComparison.Ordinal); /*Super uggly hack, SR doesn't allow one to query for it */ + } + + static bool TypeEquals (Type a, Type b) { + if (a == b) + return true; + + if (a.HasElementType) { + if (!b.HasElementType) + return false; + if (!TypeEquals (a.GetElementType (), b.GetElementType ())) + return false; + if (a.IsArray) { + if (!b.IsArray) + return false; + int rank = a.GetArrayRank (); + if (rank != b.GetArrayRank ()) + return false; + if (rank == 1 && IsBoundedVector (a) != IsBoundedVector (b)) + return false; + } else if (a.IsByRef) { + if (!b.IsByRef) + return false; + } else if (a.IsPointer) { + if (!b.IsPointer) + return false; + } + return true; + } + + if (a.IsGenericType) { + if (!b.IsGenericType) + return false; + if (a.IsGenericParameter) + return a == b; + if (a.IsGenericParameter) //previous test should have caught it + return false; + + if (a.IsGenericTypeDefinition) { + if (!b.IsGenericTypeDefinition) + return false; + } else { + if (b.IsGenericTypeDefinition) + return false; + if (!TypeEquals (a.GetGenericTypeDefinition (), b.GetGenericTypeDefinition ())) + return false; + + Type[] argsA = a.GetGenericArguments (); + Type[] argsB = b.GetGenericArguments (); + for (int i = 0; i < argsA.Length; ++i) { + if (!TypeEquals (argsA [i], argsB [i])) + return false; + } + } + } + + /* + Now only non-generic, non compound types are left. To properly deal with user + types we would have to call UnderlyingSystemType, but we let them have their + own instantiation as this is MS behavior and mcs (pre C# 4.0, at least) doesn't + depend on proper UT canonicalization. + */ + return a == b; + } + + public override bool Equals (object obj) + { + GenericInstanceKey other = obj as GenericInstanceKey; + if (other == null) + return false; + if (gtd != other.gtd) + return false; + for (int i = 0; i < args.Length; ++i) { + Type a = args [i]; + Type b = other.args [i]; + /* + We must cannonicalize as much as we can. Using equals means that some resulting types + won't have the exact same types as the argument ones. + For example, flyweight types used array, pointer and byref will should this behavior. + MCS seens to be resilient to this problem so hopefully this won't show up. + */ + if (a != b && !a.Equals (b)) + return false; + } + return true; + } + + public override int GetHashCode () + { + return hash_code; + } + } + + [ComVisible (true)] [ComDefaultInterface (typeof (_AssemblyBuilder))] -#endif [ClassInterface (ClassInterfaceType.None)] public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder { #pragma warning disable 169, 414 @@ -138,6 +250,7 @@ namespace System.Reflection.Emit NativeResourceType native_resource; readonly bool is_compiler_context; string versioninfo_culture; + Hashtable generic_instances = new Hashtable (); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void basic_init (AssemblyBuilder ab); @@ -152,19 +265,17 @@ namespace System.Reflection.Emit // remove Mono specific flag to allow enum check to pass access &= ~COMPILER_ACCESS; -#if NET_2_1 && !MONOTOUCH +#if MOONLIGHT // only "Run" is supported by Silverlight // however SMCS requires more than this but runs outside the CoreCLR sandbox if (SecurityManager.SecurityEnabled && (access != AssemblyBuilderAccess.Run)) throw new ArgumentException ("access"); #endif -#if NET_2_0 if (!Enum.IsDefined (typeof (AssemblyBuilderAccess), access)) throw new ArgumentException (string.Format (CultureInfo.InvariantCulture, "Argument value {0} is not valid.", (int) access), "access"); -#endif #if NET_4_0 if ((access & AssemblyBuilderAccess.RunAndCollect) == AssemblyBuilderAccess.RunAndCollect) @@ -238,21 +349,17 @@ namespace System.Reflection.Emit } } -#if NET_1_1 /* This is to keep signature compatibility with MS.NET */ public override string ImageRuntimeVersion { get { return base.ImageRuntimeVersion; } } -#endif -#if NET_2_0 [MonoTODO] public override bool ReflectionOnly { get { return base.ReflectionOnly; } } -#endif public void AddResourceFile (string name, string fileName) { @@ -321,12 +428,13 @@ namespace System.Reflection.Emit #endif } + // Still in use by al.exe internal void EmbedResourceFile (string name, string fileName) { EmbedResourceFile (name, fileName, ResourceAttributes.Public); } - internal void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute) + void EmbedResourceFile (string name, string fileName, ResourceAttributes attribute) { if (resources != null) { MonoResource[] new_r = new MonoResource [resources.Length + 1]; @@ -345,10 +453,9 @@ namespace System.Reflection.Emit s.Read (resources [p].data, 0, (int)len); s.Close (); } catch { - /* do something */ } } - +/* internal void EmbedResource (string name, byte[] blob, ResourceAttributes attribute) { if (resources != null) { @@ -363,11 +470,12 @@ namespace System.Reflection.Emit resources [p].attrs = attribute; resources [p].data = blob; } - -#if NET_2_0 +*/ internal void AddTypeForwarder (Type t) { if (t == null) throw new ArgumentNullException ("t"); + if (t.IsNested) + throw new ArgumentException (); if (type_forwarders == null) { type_forwarders = new Type [1] { t }; @@ -378,7 +486,6 @@ namespace System.Reflection.Emit type_forwarders = arr; } } -#endif public ModuleBuilder DefineDynamicModule (string name) { @@ -503,6 +610,8 @@ namespace System.Reflection.Emit /* * The format of the argument byte array is not documented * so this method is impossible to implement. + * + * https://connect.microsoft.com/VisualStudio/feedback/details/95784/fatal-assemblybuilder-defineunmanagedresource-byte-and-modulebuilder-defineunmanagedresource-byte-bugs-renders-them-useless */ throw new NotImplementedException (); @@ -719,6 +828,19 @@ namespace System.Reflection.Emit } } + if (res != null) { + List exceptions = null; + foreach (var type in res) { + if (type is TypeBuilder) { + if (exceptions == null) + exceptions = new List (); + exceptions.Add (new TypeLoadException (string.Format ("Type '{0}' is not finished", type.FullName))); + } + } + if (exceptions != null) + throw new ReflectionTypeLoadException (new Type [exceptions.Count], exceptions.ToArray ()); + } + return res == null ? Type.EmptyTypes : res; } @@ -783,7 +905,6 @@ namespace System.Reflection.Emit } } -#if NET_2_0 || BOOTSTRAP_NET_2_0 ModuleBuilder manifest_module; // @@ -795,14 +916,9 @@ namespace System.Reflection.Emit manifest_module = DefineDynamicModule ("Default Dynamic Module"); return manifest_module; } -#endif -#if NET_2_0 || BOOTSTRAP_NET_2_0 [MonoLimitation ("No support for PE32+ assemblies for AMD64 and IA64")] public -#else - internal -#endif void Save (string assemblyFileName, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine) { this.peKind = portableExecutableKind; @@ -929,11 +1045,9 @@ namespace System.Reflection.Emit flags |= ((uint) data [pos + 2]) << 16; flags |= ((uint) data [pos + 3]) << 24; -#if NET_2_0 // ignore PublicKey flag if assembly is not strongnamed if (sn == null) flags &= ~(uint) AssemblyNameFlags.PublicKey; -#endif } } @@ -948,9 +1062,7 @@ namespace System.Reflection.Emit } } -#if NET_2_0 [ComVisible (true)] -#endif public void SetCustomAttribute ( ConstructorInfo con, byte[] binaryAttribute) { if (con == null) throw new ArgumentNullException ("con"); @@ -1069,6 +1181,21 @@ namespace System.Reflection.Emit return an; } + /*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/ + internal Type MakeGenericType (Type gtd, Type[] typeArguments) + { + if (!IsCompilerContext) + return new MonoGenericClass (gtd, typeArguments); + + GenericInstanceKey key = new GenericInstanceKey (gtd, typeArguments); + MonoGenericClass res = (MonoGenericClass)generic_instances [key]; + if (res == null) { + res = new MonoGenericClass (gtd, typeArguments); + generic_instances [key] = res; + } + return res; + } + void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) { throw new NotImplementedException (); @@ -1088,5 +1215,93 @@ namespace System.Reflection.Emit { throw new NotImplementedException (); } + +#if NET_4_0 || MOONLIGHT + public override Type GetType (string name, bool throwOnError, bool ignoreCase) + { + if (name == null) + throw new ArgumentNullException (name); + if (name.Length == 0) + throw new ArgumentException ("name", "Name cannot be empty"); + + var res = InternalGetType (null, name, throwOnError, ignoreCase); + if (res is TypeBuilder) { + if (throwOnError) + throw new TypeLoadException (string.Format ("Could not load type '{0}' from assembly '{1}'", name, this.name)); + return null; + } + return res; + } + + public override Module GetModule (String name) + { + if (name == null) + throw new ArgumentNullException ("name"); + if (name.Length == 0) + throw new ArgumentException ("Name can't be empty"); + + if (modules == null) + return null; + + foreach (Module module in modules) { + if (module.ScopeName == name) + return module; + } + + return null; + } + + public override Module[] GetModules (bool getResourceModules) + { + Module[] modules = GetModulesInternal (); + + if (!getResourceModules) { + var result = new List (modules.Length); + foreach (Module m in modules) + if (!m.IsResource ()) + result.Add (m); + return result.ToArray (); + } + return modules; + } + + [MonoTODO ("This always returns an empty array")] + public override AssemblyName[] GetReferencedAssemblies () { + return GetReferencedAssemblies (this); + } + + public override Module[] GetLoadedModules (bool getResourceModules) + { + return GetModules (getResourceModules); + } + + //FIXME MS has issues loading satelite assemblies from SRE + public override Assembly GetSatelliteAssembly (CultureInfo culture) + { + return GetSatelliteAssembly (culture, null, true); + } + + //FIXME MS has issues loading satelite assemblies from SRE + public override Assembly GetSatelliteAssembly (CultureInfo culture, Version version) + { + return GetSatelliteAssembly (culture, version, true); + } + + public override Module ManifestModule { + get { + return GetManifestModule (); + } + } + + public override bool GlobalAssemblyCache { + get { + return false; + } + } + + public override bool IsDynamic { + get { return true; } + } +#endif } }