private static AssemblyLoadContext CreateLoadContext(ModuleLoaderConfig config) { var builder = new AssemblyLoadContextBuilder(); builder.SetMainAssemblyPath(config.MainAssemblyPath); foreach (var ext in config.PrivateAssemblies) { builder.PreferLoadContextAssembly(ext); } if (config.PreferSharedTypes) { builder.PreferDefaultLoadContext(true); } if (config.IsUnloadable) { builder.EnableUnloading(); } foreach (var assemblyName in config.SharedAssemblies) { builder.PreferDefaultLoadContextAssembly(assemblyName); } return(builder.Build()); }
private static void AddProbingPaths(AssemblyLoadContextBuilder builder, RuntimeOptions options, string tfm) { if (options.AdditionalProbingPaths == null) { return; } foreach (var item in options.AdditionalProbingPaths) { var path = item; if (path.Contains("|arch|")) { path = path.Replace("|arch|", RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant()); } if (path.Contains("|tfm|")) { if (tfm == null) { // We don't have enough information to parse this continue; } path = path.Replace("|tfm|", tfm); } builder.AddProbingPath(path); } }
/// <summary> /// Add a pre-parsed <see cref="DependencyContext" /> to the load context. /// </summary> /// <param name="builder">The builder.</param> /// <param name="dependencyContext">The dependency context.</param> /// <returns>The builder.</returns> public static AssemblyLoadContextBuilder AddDependencyContext(this AssemblyLoadContextBuilder builder, DependencyContext dependencyContext) { var ridGraph = dependencyContext.RuntimeGraph.Any() ? dependencyContext.RuntimeGraph : DependencyContext.Default.RuntimeGraph; var rid = Microsoft.DotNet.PlatformAbstractions.RuntimeEnvironment.GetRuntimeIdentifier(); var fallbackRid = GetFallbackRid(); var fallbackGraph = ridGraph.FirstOrDefault(g => g.Runtime == rid) ?? ridGraph.FirstOrDefault(g => g.Runtime == fallbackRid) ?? new RuntimeFallbacks("any"); foreach (var managed in dependencyContext.ResolveRuntimeAssemblies(fallbackGraph)) { builder.AddManagedLibrary(managed); } foreach (var library in dependencyContext.ResolveResourceAssemblies()) { foreach (var resource in library.ResourceAssemblies) { /* * For resource assemblies, look in $packageRoot/$packageId/$version/$resourceGrandparent * * For example, a deps file may contain * * "Example/1.0.0": { * "runtime": { * "lib/netcoreapp2.0/Example.dll": { } * }, * "resources": { * "lib/netcoreapp2.0/es/Example.resources.dll": { * "locale": "es" * } * } * } * * In this case, probing should happen in $packageRoot/example/1.0.0/lib/netcoreapp2.0 */ var path = Path.Combine(library.Name.ToLowerInvariant(), library.Version, Path.GetDirectoryName(Path.GetDirectoryName(resource.Path))); builder.AddResourceProbingSubpath(path); } } foreach (var native in dependencyContext.ResolveNativeAssets(fallbackGraph)) { builder.AddNativeLibrary(native); } return(builder); }
/// <summary> /// Add dependency information to a load context from a .deps.json file. /// </summary> /// <param name="builder">The builder.</param> /// <param name="depsFilePath">The full path to the .deps.json file.</param> /// <returns>The builder.</returns> public static AssemblyLoadContextBuilder AddDependencyContext(this AssemblyLoadContextBuilder builder, string depsFilePath) { var reader = new DependencyContextJsonReader(); using (var file = File.OpenRead(depsFilePath)) { var deps = reader.Read(file); builder.AddDependencyContext(deps); } return(builder); }
/// <summary> /// Add dependency information to a load context from a .deps.json file. /// </summary> /// <param name="builder">The builder.</param> /// <param name="depsFilePath">The full path to the .deps.json file.</param> /// <param name="error">An error, if one occurs while reading .deps.json</param> /// <returns>The builder.</returns> public static AssemblyLoadContextBuilder TryAddDependencyContext(this AssemblyLoadContextBuilder builder, string depsFilePath, out Exception error) { error = null; try { builder.AddDependencyContext(depsFilePath); } catch (Exception ex) { error = ex; } return(builder); }
/// <summary> /// Adds additional probing paths to a managed load context using settings found in the runtimeconfig.json /// and runtimeconfig.dev.json files. /// </summary> /// <param name="builder">The context builder</param> /// <param name="runtimeConfigPath">The path to the runtimeconfig.json file</param> /// <param name="includeDevConfig">Also read runtimeconfig.dev.json file, if present.</param> /// <param name="error">The error, if one occurs while parsing runtimeconfig.json</param> /// <returns>The builder.</returns> public static AssemblyLoadContextBuilder TryAddAdditionalProbingPathFromRuntimeConfig( this AssemblyLoadContextBuilder builder, string runtimeConfigPath, bool includeDevConfig, out Exception error) { error = null; try { var config = TryReadConfig(runtimeConfigPath); if (config == null) { return(builder); } RuntimeConfig devConfig = null; if (includeDevConfig) { var configDevPath = runtimeConfigPath.Substring(0, runtimeConfigPath.Length - JsonExt.Length) + ".dev.json"; devConfig = TryReadConfig(configDevPath); } var tfm = config.runtimeOptions?.Tfm ?? devConfig?.runtimeOptions?.Tfm; if (config.runtimeOptions != null) { AddProbingPaths(builder, config.runtimeOptions, tfm); } if (devConfig?.runtimeOptions != null) { AddProbingPaths(builder, devConfig.runtimeOptions, tfm); } if (tfm != null) { var dotnet = Process.GetCurrentProcess().MainModule.FileName; if (string.Equals(Path.GetFileNameWithoutExtension(dotnet), "dotnet", StringComparison.OrdinalIgnoreCase)) { var dotnetHome = Path.GetDirectoryName(dotnet); builder.AddProbingPath(Path.Combine(dotnetHome, "store", RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant(), tfm)); } } } catch (Exception ex) { error = ex; } return(builder); }