private EditorServicesLoader( HostLogger logger, EditorServicesConfig hostConfig, ISessionFileWriter sessionFileWriter, IReadOnlyCollection <IDisposable> loggersToUnsubscribe) { _logger = logger; _hostConfig = hostConfig; _sessionFileWriter = sessionFileWriter; _loggersToUnsubscribe = loggersToUnsubscribe; }
public EditorServicesRunner( HostLogger logger, EditorServicesConfig config, ISessionFileWriter sessionFileWriter, IReadOnlyCollection <IDisposable> loggersToUnsubscribe) { _logger = logger; _config = config; _sessionFileWriter = sessionFileWriter; _serverFactory = EditorServicesServerFactory.Create(_config.LogPath, (int)_config.LogLevel, logger); _alreadySubscribedDebug = false; _loggersToUnsubscribe = loggersToUnsubscribe; }
public EditorServicesRunner( HostLogger logger, EditorServicesConfig config, ISessionFileWriter sessionFileWriter, IReadOnlyCollection <IDisposable> loggersToUnsubscribe) { _logger = logger; _config = config; _sessionFileWriter = sessionFileWriter; // NOTE: This factory helps to isolate `Microsoft.Extensions.Logging/DependencyInjection`. _serverFactory = EditorServicesServerFactory.Create(_config.LogPath, (int)_config.LogLevel, logger); _alreadySubscribedDebug = false; _loggersToUnsubscribe = loggersToUnsubscribe; }
/// <summary> /// Create a new Editor Services loader. /// </summary> /// <param name="logger">The host logger to use.</param> /// <param name="hostConfig">The host configuration to start editor services with.</param> /// <param name="sessionFileWriter">The session file writer to write the session file with.</param> /// <returns></returns> public static EditorServicesLoader Create( HostLogger logger, EditorServicesConfig hostConfig, ISessionFileWriter sessionFileWriter, IReadOnlyCollection <IDisposable> loggersToUnsubscribe) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (hostConfig == null) { throw new ArgumentNullException(nameof(hostConfig)); } #if CoreCLR // In .NET Core, we add an event here to redirect dependency loading to the new AssemblyLoadContext we load PSES' dependencies into logger.Log(PsesLogLevel.Verbose, "Adding AssemblyResolve event handler for new AssemblyLoadContext dependency loading"); var psesLoadContext = new PsesLoadContext(s_psesDependencyDirPath); if (hostConfig.LogLevel == PsesLogLevel.Diagnostic) { AppDomain.CurrentDomain.AssemblyLoad += (object sender, AssemblyLoadEventArgs args) => { logger.Log( PsesLogLevel.Diagnostic, $"Loaded into load context {AssemblyLoadContext.GetLoadContext(args.LoadedAssembly)}: {args.LoadedAssembly}"); }; } AssemblyLoadContext.Default.Resolving += (AssemblyLoadContext defaultLoadContext, AssemblyName asmName) => { logger.Log(PsesLogLevel.Diagnostic, $"Assembly resolve event fired for {asmName}"); // We only want the Editor Services DLL; the new ALC will lazily load its dependencies automatically if (!string.Equals(asmName.Name, "Microsoft.PowerShell.EditorServices", StringComparison.Ordinal)) { return(null); } string asmPath = Path.Combine(s_psesDependencyDirPath, $"{asmName.Name}.dll"); logger.Log(PsesLogLevel.Verbose, "Loading PSES DLL using new assembly load context"); return(psesLoadContext.LoadFromAssemblyPath(asmPath)); }; #else // In .NET Framework we add an event here to redirect dependency loading in the current AppDomain for PSES' dependencies logger.Log(PsesLogLevel.Verbose, "Adding AssemblyResolve event handler for dependency loading"); if (hostConfig.LogLevel == PsesLogLevel.Diagnostic) { AppDomain.CurrentDomain.AssemblyLoad += (object sender, AssemblyLoadEventArgs args) => { logger.Log( PsesLogLevel.Diagnostic, $"Loaded {args.LoadedAssembly.GetName()}"); }; } // Unlike in .NET Core, we need to be look for all dependencies in .NET Framework, not just PSES.dll AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs args) => { logger.Log(PsesLogLevel.Diagnostic, $"Assembly resolve event fired for {args.Name}"); var asmName = new AssemblyName(args.Name); var dllName = $"{asmName.Name}.dll"; // First look for the required assembly in the .NET Framework DLL dir string baseDirAsmPath = Path.Combine(s_psesBaseDirPath, dllName); if (File.Exists(baseDirAsmPath)) { logger.Log(PsesLogLevel.Diagnostic, $"Loading {args.Name} from PSES base dir into LoadFrom context"); return(Assembly.LoadFrom(baseDirAsmPath)); } // Then look in the shared .NET Standard directory string asmPath = Path.Combine(s_psesDependencyDirPath, dllName); if (File.Exists(asmPath)) { logger.Log(PsesLogLevel.Diagnostic, $"Loading {args.Name} from PSES dependency dir into LoadFrom context"); return(Assembly.LoadFrom(asmPath)); } return(null); }; #endif return(new EditorServicesLoader(logger, hostConfig, sessionFileWriter, loggersToUnsubscribe)); }
/// <summary> /// Create a new Editor Services loader. /// </summary> /// <param name="logger">The host logger to use.</param> /// <param name="hostConfig">The host configuration to start editor services with.</param> /// <param name="sessionFileWriter">The session file writer to write the session file with.</param> /// <returns></returns> public static EditorServicesLoader Create( HostLogger logger, EditorServicesConfig hostConfig, ISessionFileWriter sessionFileWriter) => Create(logger, hostConfig, sessionFileWriter, loggersToUnsubscribe: null);