diff --git a/src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CoreCLR/CorePsAssemblyLoadContext.cs b/src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CoreCLR/CorePsAssemblyLoadContext.cs
index cb2cc44d8..2a767452d 100644
--- a/src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CoreCLR/CorePsAssemblyLoadContext.cs
+++ b/src/Microsoft.PowerShell.CoreCLR.AssemblyLoadContext/CoreCLR/CorePsAssemblyLoadContext.cs
@@ -15,9 +15,9 @@ using System.Runtime.Loader;
namespace System.Management.Automation
{
///
- /// The powershell custom AssemblyLoadContext implementation
+ /// The powershell custom assembly loader implementation
///
- internal partial class PowerShellAssemblyLoadContext : AssemblyLoadContext
+ internal partial class PowerShellAssemblyLoadContext
{
#region Resource_Strings
@@ -37,13 +37,6 @@ namespace System.Management.Automation
#region Constructor
- ///
- /// This constructor is for testability purpose only
- ///
- protected PowerShellAssemblyLoadContext()
- {
- }
-
///
/// Constructor
///
@@ -77,12 +70,18 @@ namespace System.Management.Automation
// - Key: namespace qualified type name (FullName)
// - Value: strong name of the TPA that contains the type represented by Key.
coreClrTypeCatalog = InitializeTypeCatalog();
+
+ this.loadContext = AssemblyLoadContext.Default;
+ loadContext.Resolving += Resolve;
}
#endregion Constructor
#region Fields
+ // AssemblyLoadContext used by this loader
+ private readonly AssemblyLoadContext loadContext;
+
// Serialized type catalog file
private readonly object syncObj = new object();
private readonly string[] basePaths;
@@ -118,10 +117,15 @@ namespace System.Management.Automation
#region Protected_Internal_Methods
///
- /// Implement the AssemblyLoadContext.Load(AssemblyName). Search the requested assembly in probing paths.
+ /// The global instance of PowerShellAssemblyLoadContext
+ ///
+ internal static PowerShellAssemblyLoadContext Instance { get; set; }
+
+ ///
+ /// Implement the AssemblyLoadContext.Resolving event handler. Search the requested assembly in probing paths.
/// Search the file "[assemblyName.Name][.ni].dll" in probing paths. If the file is found and it matches the requested AssemblyName, load it with LoadFromAssemblyPath.
///
- protected override Assembly Load(AssemblyName assemblyName)
+ internal Assembly Resolve(AssemblyLoadContext sender, AssemblyName assemblyName)
{
// Probe the assembly cache
Assembly asmLoaded;
@@ -153,7 +157,7 @@ namespace System.Management.Automation
if (File.Exists(asmFilePath))
{
isAssemblyFileFound = true;
- AssemblyName asmNameFound = GetAssemblyName(asmFilePath);
+ AssemblyName asmNameFound = AssemblyLoadContext.GetAssemblyName(asmFilePath);
if (IsAssemblyMatching(assemblyName, asmNameFound))
{
isAssemblyFileMatching = true;
@@ -187,8 +191,8 @@ namespace System.Management.Automation
try
{
asmLoaded = asmFilePath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase)
- ? LoadFromNativeImagePath(asmFilePath, null)
- : LoadFromAssemblyPath(asmFilePath);
+ ? loadContext.LoadFromNativeImagePath(asmFilePath, null)
+ : loadContext.LoadFromAssemblyPath(asmFilePath);
}
// Since .NET CLI built versions of PowerShell have all the
// built-in assemblies in the TPA list, the above will throw,
@@ -211,6 +215,14 @@ namespace System.Management.Automation
return asmLoaded;
}
+ ///
+ /// Load an assembly from its name.
+ ///
+ internal Assembly LoadFromAssemblyName(AssemblyName assemblyName)
+ {
+ return loadContext.LoadFromAssemblyName(assemblyName);
+ }
+
///
/// Load an assembly from its file path.
///
@@ -239,7 +251,7 @@ namespace System.Management.Automation
#endregion Validation
Assembly asmLoaded;
- AssemblyName assemblyName = GetAssemblyName(assemblyPath);
+ AssemblyName assemblyName = AssemblyLoadContext.GetAssemblyName(assemblyPath);
// Probe the assembly cache
if (TryGetAssemblyFromCache(assemblyName, out asmLoaded))
@@ -256,8 +268,8 @@ namespace System.Management.Automation
{
// Load the assembly through 'LoadFromNativeImagePath' or 'LoadFromAssemblyPath'
asmLoaded = assemblyPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase)
- ? LoadFromNativeImagePath(assemblyPath, null)
- : LoadFromAssemblyPath(assemblyPath);
+ ? loadContext.LoadFromNativeImagePath(assemblyPath, null)
+ : loadContext.LoadFromAssemblyPath(assemblyPath);
}
// Since .NET CLI built versions of PowerShell have all the
// built-in assemblies in the TPA list, the above will throw,
@@ -290,7 +302,7 @@ namespace System.Management.Automation
///
internal Assembly LoadFrom(Stream assembly)
{
- var asm = LoadFromStream(assembly);
+ var asm = loadContext.LoadFromStream(assembly);
TryAddAssemblyToCache(asm);
return asm;
}
@@ -503,8 +515,6 @@ namespace System.Management.Automation
///
public class PowerShellAssemblyLoadContextInitializer
{
- private static bool IsInitialized = false;
-
// Porting note: it's much easier to send an LPStr on Linux
private const UnmanagedType stringType =
#if LINUX
@@ -519,19 +529,9 @@ namespace System.Management.Automation
///
public static void SetPowerShellAssemblyLoadContext([MarshalAs(stringType)]string basePaths)
{
- if (!IsInitialized)
+ if (PowerShellAssemblyLoadContext.Instance == null)
{
- var psAsmLoadContext = new PowerShellAssemblyLoadContext(basePaths);
- try
- {
- AssemblyLoadContext.InitializeDefaultContext(psAsmLoadContext);
- }
- catch (System.InvalidOperationException)
- {
- // We may not be able to set the default context. If we're under the
- // xUnit test harness, it has already been set.
- }
- IsInitialized = true;
+ PowerShellAssemblyLoadContext.Instance = new PowerShellAssemblyLoadContext(basePaths);
}
}
}
diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs
index edb4de9d6..faeda630f 100644
--- a/src/System.Management.Automation/utils/ClrFacade.cs
+++ b/src/System.Management.Automation/utils/ClrFacade.cs
@@ -391,13 +391,7 @@ namespace System.Management.Automation
{
if (_psLoadContext == null)
{
- _psLoadContext = AssemblyLoadContext.Default as PowerShellAssemblyLoadContext;
- if (_psLoadContext == null)
- {
- // The default load context may not be ours. This can happen during,
- // for instance, xUnit testing.
- _psLoadContext = new PowerShellAssemblyLoadContext(String.Empty);
- }
+ _psLoadContext = PowerShellAssemblyLoadContext.Instance;
}
return _psLoadContext;
}