From 44ba0bb28fcb54cb443af4bf90d222cddb2dd489 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 20 May 2016 14:14:30 -0700 Subject: [PATCH] Switch from AssemblyLoadContext.InitializeDefaultContext to AssemblyLoadContext.Resolving event AssemblyLoadContext.InitializeDefaultContext was removed for .NET Core 1.0 RTM. Replaced its use with AssemblyLoadContext.Resolving event. --- .../CoreCLR/CorePsAssemblyLoadContext.cs | 64 +++++++++---------- .../utils/ClrFacade.cs | 8 +-- 2 files changed, 33 insertions(+), 39 deletions(-) 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; }