Przeglądaj źródła

[corlib] Bring AssemblyName(string) to the happy C# world.

Rodrigo Kumpera 9 lat temu
rodzic
commit
ff86e021c0

+ 9 - 0
mcs/class/corlib/Mono/RuntimeMarshal.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
 
 namespace Mono {
 	internal static class RuntimeMarshal {
@@ -10,6 +11,11 @@ namespace Mono {
 			}
 		}
 
+		internal static SafeStringMarshal MarshalString (string str)
+		{
+			return new SafeStringMarshal (str);
+		}
+
 		static int DecodeBlobSize (IntPtr in_ptr, out IntPtr out_ptr)
 		{
 			uint size;
@@ -52,5 +58,8 @@ namespace Mono {
 				return c - 'a' + 10;
 			return c - 'A' + 10;
 		}
+
+		[MethodImpl (MethodImplOptions.InternalCall)]
+		internal static extern void FreeAssemblyName (ref MonoAssemblyName name);
 	}
 }

+ 56 - 40
mcs/class/corlib/System.Reflection/AssemblyName.cs

@@ -85,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")]
@@ -454,53 +466,57 @@ namespace System.Reflection {
 		[MethodImplAttribute (MethodImplOptions.InternalCall)]
 		static extern unsafe MonoAssemblyName* GetNativeName (IntPtr assembly_ptr);
 
-		internal static AssemblyName Create (Assembly assembly, bool fillCodebase)
+		internal unsafe void FillName (MonoAssemblyName *native, string codeBase, bool addVersion, bool addPublickey, bool defaultToken)
 		{
-			AssemblyName aname = new AssemblyName ();
-			unsafe {
-				MonoAssemblyName *native = GetNativeName (assembly._mono_assembly);
+			this.name = RuntimeMarshal.PtrToUtf8String (native->name);
 
-				aname.name = RuntimeMarshal.PtrToUtf8String (native->name);
+			this.major = native->major;
+			this.minor = native->minor;
+			this.build = native->build;
+			this.revision = native->revision;
 
-				aname.major = native->major;
-				aname.minor = native->minor;
-				aname.build = native->build;
-				aname.revision = native->revision;
+			this.flags = (AssemblyNameFlags)native->flags;
 
-				aname.flags = (AssemblyNameFlags)native->flags;
+			this.hashalg = (AssemblyHashAlgorithm)native->hash_alg;
 
-				aname.hashalg = (AssemblyHashAlgorithm)native->hash_alg;
+			this.versioncompat = AssemblyVersionCompatibility.SameMachine;
+			this.processor_architecture = (ProcessorArchitecture)native->arch;
 
-				aname.versioncompat = AssemblyVersionCompatibility.SameMachine;
-				aname.processor_architecture = (ProcessorArchitecture)native->arch;
+			if (addVersion)
+				this.version = new Version (this.major, this.minor, this.build, this.revision);
 
-				aname.version = new Version (aname.major, aname.minor, aname.build, aname.revision);
+			this.codebase = codeBase;
 
-				if (fillCodebase)
-					aname.codebase = assembly.CodeBase;
+			if (native->culture != IntPtr.Zero)
+				this.cultureinfo = CultureInfo.CreateCulture ( RuntimeMarshal.PtrToUtf8String (native->culture), false);
 
-				if (native->culture != IntPtr.Zero)
-					aname.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;
+			}
 
-				if (native->public_key != IntPtr.Zero) {
-					aname.publicKey = RuntimeMarshal.DecodeBlobArray (native->public_key);
-					aname.flags |= AssemblyNameFlags.PublicKey;
-				} else {
-					aname.publicKey = EmptyArray<byte>.Value;
-					aname.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;
+			}
+		}
 
-				// 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++]);
-					}
-					aname.keyToken = keyToken;
-				} else {
-					aname.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;
 		}

+ 1 - 0
mono/metadata/assembly.c

@@ -1999,6 +1999,7 @@ mono_assembly_name_free (MonoAssemblyName *aname)
 	g_free ((void *) aname->name);
 	g_free ((void *) aname->culture);
 	g_free ((void *) aname->hash_value);
+	g_free ((guint8*) aname->public_key);
 }
 
 static gboolean

+ 4 - 1
mono/metadata/icall-def.h

@@ -68,6 +68,9 @@ ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFr
 ICALL_TYPE(RTPTRARRAY, "Mono.RuntimeGPtrArrayHandle", RTPTRARRAY_1)
 ICALL(RTPTRARRAY_1, "GPtrArrayFree", ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree)
 
+ICALL_TYPE(RTMARSHAL, "Mono.RuntimeMarshal", RTMARSHAL_1)
+ICALL(RTMARSHAL_1, "FreeAssemblyName", ves_icall_Mono_RuntimeMarshal_FreeAssemblyName)
+
 ICALL_TYPE(SAFESTRMARSHAL, "Mono.SafeStringMarshal", SAFESTRMARSHAL_1)
 ICALL(SAFESTRMARSHAL_1, "GFree", ves_icall_Mono_SafeStringMarshal_GFree)
 ICALL(SAFESTRMARSHAL_2, "StringToUtf8", ves_icall_Mono_SafeStringMarshal_StringToUtf8)
@@ -495,7 +498,7 @@ ICALL(ASSEM_26, "load_with_partial_name", ves_icall_System_Reflection_Assembly_l
 
 ICALL_TYPE(ASSEMN, "System.Reflection.AssemblyName", ASSEMN_0)
 ICALL(ASSEMN_0, "GetNativeName", ves_icall_System_Reflection_AssemblyName_GetNativeName)
-ICALL(ASSEMN_1, "ParseName", ves_icall_System_Reflection_AssemblyName_ParseName)
+ICALL(ASSEMN_3, "ParseAssemblyName", ves_icall_System_Reflection_AssemblyName_ParseAssemblyName)
 ICALL(ASSEMN_2, "get_public_token", mono_digest_get_public_token)
 
 ICALL_TYPE(CATTR_DATA, "System.Reflection.CustomAttributeData", CATTR_DATA_1)

+ 9 - 26
mono/metadata/icall.c

@@ -5756,35 +5756,18 @@ ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly,
 	return res;
 }
 
-ICALL_EXPORT gboolean
-ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
+ICALL_EXPORT void
+ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
 {
-	MonoError error;
-	MonoAssemblyName aname;
-	MonoDomain *domain = mono_object_domain (name);
-	char *val;
-	gboolean is_version_defined;
-	gboolean is_token_defined;
-
-	aname.public_key = NULL;
-	val = mono_string_to_utf8_checked (assname, &error);
-	if (mono_error_set_pending_exception (&error))
-		return FALSE;
-
-	if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
-		g_free ((guint8*) aname.public_key);
-		g_free (val);
-		return FALSE;
-	}
-	
-	fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
-	mono_error_set_pending_exception (&error);
+	mono_assembly_name_free (aname);
+}
 
-	mono_assembly_name_free (&aname);
-	g_free ((guint8*) aname.public_key);
-	g_free (val);
+ICALL_EXPORT gboolean
+ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
+{
+	*is_version_definited = *is_token_defined = FALSE;
 
-	return TRUE;
+	return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
 }
 
 ICALL_EXPORT MonoReflectionType*