Merge pull request #3528 from BrzVlad/fix-sgen-check-before-collections
[mono.git] / mcs / class / corlib / System.Reflection / AssemblyName.cs
index 9da34563f241ccf3e575df1e5acc425dfae28f90..86241d82d2b223c5e2d93fd4047ce7e753ec3e8a 100644 (file)
@@ -40,6 +40,7 @@ using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
 using System.IO;
 
+using Mono;
 using Mono.Security;
 using Mono.Security.Cryptography;
 
@@ -84,17 +85,29 @@ namespace System.Reflection {
                }
 
                [MethodImpl (MethodImplOptions.InternalCall)]
-               static extern bool ParseName (AssemblyName aname, string assemblyName);
-               
+               static extern bool ParseAssemblyName (IntPtr name, out MonoAssemblyName aname, out bool is_version_definited, out bool is_token_defined);
+
                public AssemblyName (string assemblyName)
                {
                        if (assemblyName == null)
                                throw new ArgumentNullException ("assemblyName");
                        if (assemblyName.Length < 1)
                                throw new ArgumentException ("assemblyName cannot have zero length.");
-                               
-                       if (!ParseName (this, assemblyName))
-                               throw new FileLoadException ("The assembly name is invalid.");
+
+                       using (var name = RuntimeMarshal.MarshalString (assemblyName)) {
+                               MonoAssemblyName nativeName;
+                               bool isVersionDefined, isTokenDefined;
+                               //ParseName free the name if it fails.
+                               if (!ParseAssemblyName (name.Value, out nativeName, out isVersionDefined, out isTokenDefined))
+                                       throw new FileLoadException ("The assembly name is invalid.");
+                               try {
+                                       unsafe {
+                                               this.FillName (&nativeName, null, isVersionDefined, false, isTokenDefined);
+                                       }
+                               } finally {
+                                       RuntimeMarshal.FreeAssemblyName (ref nativeName);
+                               }
+                       }
                }
                
                [MonoLimitation ("Not used, as the values are too limited;  Mono supports more")]
@@ -433,6 +446,9 @@ namespace System.Reflection {
                        get {
                                return (cultureinfo == null)? null : cultureinfo.Name;
                        }
+                       set {
+                               throw new NotImplementedException ();
+                       }
                }
 
                [ComVisibleAttribute(false)]
@@ -444,5 +460,63 @@ namespace System.Reflection {
                                contentType = value;
                        }
                }
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr);
+
+               internal unsafe void FillName (MonoAssemblyName *native, string codeBase, bool addVersion, bool addPublickey, bool defaultToken)
+               {
+                       this.name = RuntimeMarshal.PtrToUtf8String (native->name);
+
+                       this.major = native->major;
+                       this.minor = native->minor;
+                       this.build = native->build;
+                       this.revision = native->revision;
+
+                       this.flags = (AssemblyNameFlags)native->flags;
+
+                       this.hashalg = (AssemblyHashAlgorithm)native->hash_alg;
+
+                       this.versioncompat = AssemblyVersionCompatibility.SameMachine;
+                       this.processor_architecture = (ProcessorArchitecture)native->arch;
+
+                       if (addVersion)
+                               this.version = new Version (this.major, this.minor, this.build, this.revision);
+
+                       this.codebase = codeBase;
+
+                       if (native->culture != IntPtr.Zero)
+                               this.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false);
+
+                       if (native->public_key != IntPtr.Zero) {
+                               this.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key);
+                               this.flags |= AssemblyNameFlags.PublicKey;
+                       } else if (addPublickey) {
+                               this.publicKey = EmptyArray<byte>.Value;
+                               this.flags |= AssemblyNameFlags.PublicKey;
+                       }
+
+                       // MonoAssemblyName keeps the public key token as an hexadecimal string
+                       if (native->public_key_token [0] != 0) {
+                               byte[] keyToken = new byte [8];
+                               for (int i = 0, j = 0; i < 8; ++i) {
+                                       keyToken [i] = (byte)(RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]) << 4);
+                                       keyToken [i] |= (byte)RuntimeMarshal.AsciHexDigitValue (native->public_key_token [j++]);
+                               }
+                               this.keyToken = keyToken;
+                       } else if (defaultToken) {
+                               this.keyToken = EmptyArray<byte>.Value;
+                       }
+               }
+
+               internal static AssemblyName Create (Assembly assembly, bool fillCodebase)
+               {
+                       AssemblyName aname = new AssemblyName ();
+                       unsafe {
+                               MonoAssemblyName *native = GetNativeName (assembly._mono_assembly);
+                               aname.FillName (native, fillCodebase ? assembly.CodeBase : null, true, true, true);
+                       }
+                       return aname;
+               }
        }
 }