Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ResourceManager.BaseName work as documented. #75497

Merged
merged 4 commits into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 ? "<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)}");
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,43 +321,36 @@ private static ResourceSet InternalGetResourceSetFromSerializedData(Stream store
return rs;
}

private Stream? GetManifestResourceStream(Assembly satellite, string fileName)
private static Stream? GetManifestResourceStream(Assembly satellite, string fileName)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
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);
}

// Looks up a .resources file in the assembly manifest using
// 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<char>(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)
{
canonicalName = existingName;
}
else
{
throw new MissingManifestResourceException(SR.Format(SR.MissingManifestResource_MultipleBlobs, resourceName, satellite.ToString()));
throw new MissingManifestResourceException(SR.Format(SR.MissingManifestResource_MultipleBlobs, name, satellite.ToString()));
}
}
}
Expand Down Expand Up @@ -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)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ internal sealed class CultureNameResourceSetPair

private Dictionary<string, ResourceSet>? _resourceSets;
private readonly string? _moduleDir; // For assembly-ignorant directory location
private readonly Type? _locationInfo; // For Assembly or type-based directory layout

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
private readonly Type? _userResourceSet; // Which ResourceSet instance to create
Expand Down Expand Up @@ -227,9 +226,13 @@ public ResourceManager(Type resourceSource)
if (resourceSource is not RuntimeType)
throw new ArgumentException(SR.Argument_MustBeRuntimeType);

_locationInfo = resourceSource;
MainAssembly = _locationInfo.Assembly;
BaseNameField = resourceSource.Name;
MainAssembly = resourceSource.Assembly;

string? nameSpace = resourceSource.Namespace;
char c = Type.Delimiter;
BaseNameField = nameSpace is null
? resourceSource.Name
: string.Concat(nameSpace, new ReadOnlySpan<char>(in c), resourceSource.Name);
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved

CommonAssemblyInit();
}
Expand Down Expand Up @@ -407,7 +410,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);
Expand Down Expand Up @@ -747,9 +750,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;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
Assert.Equal("System.Resources.Tests.Resources.TestResx", manager.BaseName);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joperezr any other test cases you'd like to see?


Expand Down