From ed3046bdb815512929262a062ae2f7dea82ea702 Mon Sep 17 00:00:00 2001 From: Michael Adelson Date: Mon, 12 Sep 2022 20:30:19 -0400 Subject: [PATCH] Make ResourceManager.BaseName work as documented. This property is documented to return the "qualified namespace name and the root resource name of a resource file". However, previously when constructing a ResourceManager with a Type the BaseName property would instead return the name of the type without its namespace. fix #74918 --- .../Resources/FileBasedResourceGroveler.cs | 5 +--- .../ManifestBasedResourceGroveler.cs | 25 +++++-------------- .../src/System/Resources/ResourceManager.cs | 12 +++++---- .../tests/ResourceManagerTests.cs | 5 +++- 4 files changed, 18 insertions(+), 29 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs index ad98312fadd85..6bf0bd754fe96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs @@ -47,10 +47,7 @@ public FileBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediato // If we've hit top of the Culture tree, return. if (culture.HasInvariantCultureName) { - // We really don't think this should happen - we always - // expect the neutral locale's resources to be present. - string? locationInfo = _mediator.LocationInfo == null ? "" : _mediator.LocationInfo.FullName; - throw new MissingManifestResourceException($"{SR.MissingManifestResource_NoNeutralDisk}{Environment.NewLineConst}baseName: {_mediator.BaseNameField} locationInfo: {locationInfo} fileName: {_mediator.GetResourceFileName(culture)}"); + throw new MissingManifestResourceException($"{SR.MissingManifestResource_NoNeutralDisk}{Environment.NewLineConst}baseName: {_mediator.BaseNameField} fileName: {_mediator.GetResourceFileName(culture)}"); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs index fa7bfb44b4bfc..6a100e23251af 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs @@ -321,12 +321,12 @@ private static ResourceSet InternalGetResourceSetFromSerializedData(Stream store return rs; } - private Stream? GetManifestResourceStream(Assembly satellite, string fileName) + private static Stream? GetManifestResourceStream(Assembly satellite, string fileName) { Debug.Assert(satellite != null, "satellite shouldn't be null; check caller"); Debug.Assert(fileName != null, "fileName shouldn't be null; check caller"); - return satellite.GetManifestResourceStream(_mediator.LocationInfo!, fileName) ?? + return satellite.GetManifestResourceStream(fileName) ?? CaseInsensitiveManifestResourceStreamLookup(satellite, fileName); } @@ -334,22 +334,15 @@ private static ResourceSet InternalGetResourceSetFromSerializedData(Stream store // case-insensitive lookup rules. Yes, this is slow. The metadata // dev lead refuses to make all assembly manifest resource lookups case-insensitive, // even optionally case-insensitive. - private Stream? CaseInsensitiveManifestResourceStreamLookup(Assembly satellite, string name) + private static Stream? CaseInsensitiveManifestResourceStreamLookup(Assembly satellite, string name) { Debug.Assert(satellite != null, "satellite shouldn't be null; check caller"); Debug.Assert(name != null, "name shouldn't be null; check caller"); - string? nameSpace = _mediator.LocationInfo?.Namespace; - - char c = Type.Delimiter; - string resourceName = nameSpace != null && name != null ? - string.Concat(nameSpace, new ReadOnlySpan(in c), name) : - string.Concat(nameSpace, name); - string? canonicalName = null; foreach (string existingName in satellite.GetManifestResourceNames()) { - if (string.Equals(existingName, resourceName, StringComparison.InvariantCultureIgnoreCase)) + if (string.Equals(existingName, name, StringComparison.InvariantCultureIgnoreCase)) { if (canonicalName == null) { @@ -357,7 +350,7 @@ private static ResourceSet InternalGetResourceSetFromSerializedData(Stream store } else { - throw new MissingManifestResourceException(SR.Format(SR.MissingManifestResource_MultipleBlobs, resourceName, satellite.ToString())); + throw new MissingManifestResourceException(SR.Format(SR.MissingManifestResource_MultipleBlobs, name, satellite.ToString())); } } } @@ -488,16 +481,10 @@ private void HandleResourceStreamMissing(string fileName) const string MesgFailFast = System.CoreLib.Name + ResourceManager.ResFileExtension + " couldn't be found! Large parts of the BCL won't work!"; System.Environment.FailFast(MesgFailFast); } - // We really don't think this should happen - we always - // expect the neutral locale's resources to be present. - string resName = string.Empty; - if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null) - resName = _mediator.LocationInfo.Namespace + Type.Delimiter; - resName += fileName; Debug.Assert(_mediator.MainAssembly != null); throw new MissingManifestResourceException( SR.Format(SR.MissingManifestResource_NoNeutralAsm, - resName, _mediator.MainAssembly.GetName().Name, GetManifestResourceNamesList(_mediator.MainAssembly))); + fileName, _mediator.MainAssembly.GetName().Name, GetManifestResourceNamesList(_mediator.MainAssembly))); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs index 0693779839403..3a6b349ec8dbc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs @@ -229,7 +229,12 @@ public ResourceManager(Type resourceSource) _locationInfo = resourceSource; MainAssembly = _locationInfo.Assembly; - BaseNameField = resourceSource.Name; + + string? nameSpace = resourceSource.Namespace; + char c = Type.Delimiter; + BaseNameField = nameSpace is null + ? resourceSource.Name + : string.Concat(nameSpace, new ReadOnlySpan(in c), resourceSource.Name); CommonAssemblyInit(); } @@ -407,7 +412,7 @@ protected virtual string GetResourceFileName(CultureInfo culture) { string fileName = GetResourceFileName(culture); Debug.Assert(MainAssembly != null); - Stream? stream = MainAssembly.GetManifestResourceStream(_locationInfo!, fileName); + Stream? stream = MainAssembly.GetManifestResourceStream(fileName); if (createIfNotExists && stream != null) { rs = ((ManifestBasedResourceGroveler)_resourceGroveler).CreateResourceSet(stream, MainAssembly); @@ -747,9 +752,6 @@ internal ResourceManagerMediator(ResourceManager rm) // NEEDED ONLY BY FILE-BASED internal string? ModuleDir => _rm._moduleDir; - // NEEDED BOTH BY FILE-BASED AND ASSEMBLY-BASED - internal Type? LocationInfo => _rm._locationInfo; - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] internal Type? UserResourceSet => _rm._userResourceSet; diff --git a/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs index ebdac1cd0c48a..7ab1d3348e563 100644 --- a/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs +++ b/src/libraries/System.Resources.ResourceManager/tests/ResourceManagerTests.cs @@ -204,7 +204,10 @@ public static void UsingResourceSet() [Fact] public static void BaseName() { - var manager = new ResourceManager("System.Resources.Tests.Resources.TestResx", typeof(ResourceManagerTests).GetTypeInfo().Assembly); + var manager = new ResourceManager("System.Resources.Tests.Resources.TestResx", typeof(ResourceManagerTests).Assembly); + Assert.Equal("System.Resources.Tests.Resources.TestResx", manager.BaseName); + + manager = new(typeof(System.Resources.Tests.Resources.TestResx)); Assert.Equal("System.Resources.Tests.Resources.TestResx", manager.BaseName); }