Skip to content

Commit 00612c8

Browse files
sdmacleadotnet-bot
authored andcommitted
Fix Satellite Assembly loading (dotnet/coreclr#24191)
* Fix Satellite Assembly loading When loading satellite assemblies, we should probe next to the parent assembly and load into the same AssemblyLoadContext as the parent assembly. Disable fallback probing for satellite assemblies. Add AssemblyLoadContext.Resolving handler to probe for satellite assemblies next to parent Fixes mono#20979 * Call ResolveSatelliteAssembly from native Only call ResolveSatelliteAssembly from native when resolving a satellite assembly * PR Feedback Minimize string creation Remove unnecessary if null checks Eliminate corner cases by only allowing one case insensitive matching directory. * ResolveSatelliteAssembly should ... ResolveSatelliteAssembly should always be called on the ALC which loaded parentAssembly Simplify code. Add Debug.Assert * Remove case insensitive culture search * PR Feedback * Fix parentAssembly logic * Fixes from initial testing * Add probe for lower case culture name * PR feedback Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
1 parent 8823d16 commit 00612c8

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

netcore/System.Private.CoreLib/shared/System/Runtime/Loader/AssemblyLoadContext.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public event Func<Assembly, string, IntPtr> ResolvingUnmanagedDll
187187
//
188188
// Inputs: The AssemblyLoadContext and AssemblyName to be loaded
189189
// Returns: The Loaded assembly object.
190-
public event Func<AssemblyLoadContext, AssemblyName, Assembly> Resolving
190+
public event Func<AssemblyLoadContext, AssemblyName, Assembly?> Resolving
191191
{
192192
add
193193
{
@@ -555,6 +555,43 @@ public void Dispose()
555555
}
556556
}
557557
}
558+
559+
private Assembly? ResolveSatelliteAssembly(AssemblyName assemblyName)
560+
{
561+
// Called by native runtime when CultureName is not empty
562+
Debug.Assert(assemblyName.CultureName?.Length > 0);
563+
564+
string satelliteSuffix = ".resources";
565+
566+
if (assemblyName.Name == null || !assemblyName.Name.EndsWith(satelliteSuffix, StringComparison.Ordinal))
567+
return null;
568+
569+
string parentAssemblyName = assemblyName.Name.Substring(0, assemblyName.Name.Length - satelliteSuffix.Length);
570+
571+
Assembly parentAssembly = LoadFromAssemblyName(new AssemblyName(parentAssemblyName));
572+
573+
AssemblyLoadContext parentALC = GetLoadContext(parentAssembly)!;
574+
575+
string parentDirectory = Path.GetDirectoryName(parentAssembly.Location)!;
576+
577+
string assemblyPath = Path.Combine(parentDirectory, assemblyName.CultureName!, $"{assemblyName.Name}.dll");
578+
579+
if (Internal.IO.File.InternalExists(assemblyPath))
580+
{
581+
return parentALC.LoadFromAssemblyPath(assemblyPath);
582+
}
583+
else if (Path.IsCaseSensitive)
584+
{
585+
assemblyPath = Path.Combine(parentDirectory, assemblyName.CultureName!.ToLowerInvariant(), $"{assemblyName.Name}.dll");
586+
587+
if (Internal.IO.File.InternalExists(assemblyPath))
588+
{
589+
return parentALC.LoadFromAssemblyPath(assemblyPath);
590+
}
591+
}
592+
593+
return null;
594+
}
558595
}
559596

560597
internal sealed class DefaultAssemblyLoadContext : AssemblyLoadContext

0 commit comments

Comments
 (0)