protected virtual void Dispose(bool disposing) { if (!this.disposed && disposing) { this.disposing = true; GC.Collect(); GC.WaitForPendingFinalizers(); this.hostTypesProvider = null; this.remoteTypesProvider = null; this.dependencyPathProvider = null; this.probingPathsProvider = null; this.runtimePlatformContext = null; this.depsFileProvider = null; this.pluginDependencyResolver = null; this.pluginDependencyContext = null; this.assemblyLoadStrategy = null; // Unload any loaded native assemblies foreach (var nativeAssembly in this.loadedNativeLibraries) { this.nativeAssemblyUnloader.UnloadNativeAssembly(nativeAssembly.Key, nativeAssembly.Value); } this.loadedNativeLibraries = null; this.nativeAssemblyUnloader = null; } this.disposed = true; }
public virtual NativeAssembly LoadUnmanagedDll( string initialPluginLoadDirectory, string unmanagedDllName, IPluginDependencyContext pluginDependencyContext, Func <string, string, ValueOrProceed <string> > loadFromDependencyContext, Func <string, string, ValueOrProceed <string> > loadFromRemote, Func <string, string, ValueOrProceed <IntPtr> > loadFromAppDomain) { ValueOrProceed <string> valueOrProceed = ValueOrProceed <string> .FromValue(String.Empty, true); ValueOrProceed <IntPtr> ptrValueOrProceed = ValueOrProceed <IntPtr> .FromValue(IntPtr.Zero, true); valueOrProceed = loadFromDependencyContext(initialPluginLoadDirectory, unmanagedDllName); if (valueOrProceed.CanProceed) { ptrValueOrProceed = loadFromAppDomain(initialPluginLoadDirectory, unmanagedDllName); } if (valueOrProceed.CanProceed && ptrValueOrProceed.CanProceed) { valueOrProceed = loadFromRemote(initialPluginLoadDirectory, unmanagedDllName); } return(NativeAssembly.Create(valueOrProceed.Value, ptrValueOrProceed.Value)); }
public async Task <IAssemblyShim> LoadPluginAssembly(IPluginLoadContext pluginLoadContext) { if (pluginLoadContext == null) { throw new ArgumentNullException(nameof(pluginLoadContext)); } var fullPathToAssembly = pluginLoadContext.FullPathToPluginAssembly.ThrowIfNullOrEmpty(nameof(pluginLoadContext.FullPathToPluginAssembly)); if (!Path.IsPathRooted(fullPathToAssembly)) { throw new AssemblyLoadingException($"FullPathToPluginAssembly {pluginLoadContext.FullPathToPluginAssembly} is not rooted, this must be a absolute path!"); } this.fullPathToPluginAssembly = pluginLoadContext.FullPathToPluginAssembly; this.initialPluginLoadDirectory = Path.GetDirectoryName(fullPathToPluginAssembly); this.nativeDependencyLoadPreference = pluginLoadContext.NativeDependencyLoadPreference; GuardIfAlreadyLoaded(fullPathToPluginAssembly); this.resolver = this.assemblyDependencyResolverFactory(fullPathToPluginAssembly); this.pluginDependencyContext = await this.pluginDependencyContextProvider.FromPluginLoadContext(pluginLoadContext); this.pluginDependencyResolver = this.pluginDependencyResolverFactory(); this.assemblyLoadStrategy = this.assemblyLoadStrategyFactory(); this.pluginPlatformVersion = pluginLoadContext.PluginPlatformVersion ?? PluginPlatformVersion.Empty(); var ensuredPath = this.fileSystemUtilities.EnsureFileExists(fullPathToPluginAssembly); using (var pluginStream = await this.fileSystemUtilities.ReadFileFromDisk(ensuredPath)) { return(new PriseAssembly(LoadAndAddToWeakReferences(pluginStream))); } }
public IAssemblyLoadStrategy ProvideAssemblyLoadStrategy( IPluginLogger logger, IPluginLoadContext pluginLoadContext, IPluginDependencyContext pluginDependencyContext) { return(new DefaultAssemblyLoadStrategy(logger, pluginLoadContext, pluginDependencyContext)); }
public DefaultAssemblyLoadStrategy( IPluginLogger logger, IPluginLoadContext pluginLoadContext, IPluginDependencyContext pluginDependencyContext) { this.logger = logger.ThrowIfNull(nameof(logger)); this.pluginLoadContext = pluginLoadContext.ThrowIfNull(nameof(pluginLoadContext)); this.pluginDependencyContext = pluginDependencyContext.ThrowIfNull(nameof(pluginDependencyContext)); }
protected virtual void Dispose(bool disposing) { if (!this.disposed && disposing) { this.disposing = true; GC.Collect(); GC.WaitForPendingFinalizers(); if (this.assemblyReferences != null) { foreach (var reference in this.assemblyReferences) { // https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability#use-collectible-assemblyloadcontext for (int i = 0; reference.IsAlive && (i < 10); i++) { GC.Collect(); GC.WaitForPendingFinalizers(); } } } // Unload any loaded native assemblies foreach (var nativeAssembly in this.loadedNativeLibraries) { this.nativeAssemblyUnloader.UnloadNativeAssembly(nativeAssembly.Key, nativeAssembly.Value); } this.loadedPlugins.Clear(); this.assemblyReferences.Clear(); this.loadedNativeLibraries.Clear(); this.pluginDependencyContext?.Dispose(); this.pluginDependencyResolver?.Dispose(); this.resolver?.Dispose(); this.resolver = null; this.loadedNativeLibraries = null; this.loadedPlugins = null; this.assemblyReferences = null; this.assemblyLoadStrategy = null; this.pluginDependencyContext = null; this.pluginDependencyResolver = null; this.fullPathToPluginAssembly = null; this.initialPluginLoadDirectory = null; this.pluginPlatformVersion = null; this.nativeAssemblyUnloader = null; this.pluginDependencyResolverFactory = null; this.assemblyLoadStrategyFactory = null; this.assemblyDependencyResolverFactory = null; this.fileSystemUtilities = null; this.runtimeDefaultAssemblyLoadContext = null; this.pluginDependencyContextProvider = null; } this.disposed = true; }
protected virtual void Dispose(bool disposing) { if (!this.disposed && disposing) { this.disposing = true; GC.Collect(); GC.WaitForPendingFinalizers(); this.hostTypesProvider = null; this.remoteTypesProvider = null; this.dependencyPathProvider = null; this.probingPathsProvider = null; this.runtimePlatformContext = null; this.depsFileProvider = null; this.pluginDependencyResolver = null; this.pluginDependencyContext = null; this.assemblyLoadStrategy = null; if (this.assemblyReferences != null) { foreach (var reference in this.assemblyReferences) { // https://docs.microsoft.com/en-us/dotnet/standard/assembly/unloadability#use-collectible-assemblyloadcontext for (int i = 0; reference.IsAlive && (i < 10); i++) { GC.Collect(); GC.WaitForPendingFinalizers(); } } } this.loadedPlugins.Clear(); this.loadedPlugins = null; this.assemblyReferences.Clear(); this.assemblyReferences = null; // Unload any loaded native assemblies foreach (var nativeAssembly in this.loadedNativeLibraries) { this.nativeAssemblyUnloader.UnloadNativeAssembly(nativeAssembly.Key, nativeAssembly.Value); } this.loadedNativeLibraries = null; this.nativeAssemblyUnloader = null; this.options = null; } this.disposed = true; }
public virtual AssemblyFromStrategy LoadAssembly( string initialPluginLoadDirectory, AssemblyName assemblyName, IPluginDependencyContext pluginDependencyContext, Func <string, AssemblyName, ValueOrProceed <AssemblyFromStrategy> > loadFromDependencyContext, Func <string, AssemblyName, ValueOrProceed <AssemblyFromStrategy> > loadFromRemote, Func <string, AssemblyName, ValueOrProceed <RuntimeAssemblyShim> > loadFromAppDomain) { if (assemblyName.Name == null) { return(null); } Debug.WriteLine($"{initialPluginLoadDirectory} Loading {assemblyName.Name} {assemblyName.Version}"); ValueOrProceed <AssemblyFromStrategy> valueOrProceed = ValueOrProceed <AssemblyFromStrategy> .FromValue(null, true); var isHostAssembly = IsHostAssembly(assemblyName, pluginDependencyContext); var isRemoteAssembly = IsRemoteAssembly(assemblyName, pluginDependencyContext); if (isHostAssembly && !isRemoteAssembly) // Load from Default App Domain (host) { Debug.WriteLine($"{initialPluginLoadDirectory} Loading {assemblyName.Name} {assemblyName.Version} from appDomain"); var assemblyShim = loadFromAppDomain(initialPluginLoadDirectory, assemblyName); if (assemblyShim.Value != null) { switch (assemblyShim.Value.RuntimeLoadFlag) { case RuntimeLoadFlag.FromRequestedVersion: return(null); // fallback to default loading mechanism case RuntimeLoadFlag.FromRuntimeVersion: return(AssemblyFromStrategy.NotReleasable(assemblyShim.Value.Assembly)); } } } if (valueOrProceed.CanProceed) { valueOrProceed = loadFromDependencyContext(initialPluginLoadDirectory, assemblyName); } Debug.WriteLineIf(!valueOrProceed.CanProceed, $"{initialPluginLoadDirectory} Loaded {assemblyName.Name} {assemblyName.Version} from dependency context"); if (valueOrProceed.CanProceed) { valueOrProceed = loadFromRemote(initialPluginLoadDirectory, assemblyName); Debug.WriteLineIf(!valueOrProceed.CanProceed, $"{initialPluginLoadDirectory} Loaded {assemblyName.Name} {assemblyName.Version} from remote"); } return(valueOrProceed.Value); }
public virtual Assembly LoadPluginAssembly(IPluginLoadContext pluginLoadContext) { GuardIfAlreadyLoaded(pluginLoadContext?.PluginAssemblyName); this.pluginDependencyContext = PluginDependencyContext.FromPluginAssembly <T>( pluginLoadContext, this.hostFrameworkProvider, this.hostTypesProvider.ProvideHostTypes(), this.remoteTypesProvider.ProvideRemoteTypes(), this.runtimePlatformContext, this.depsFileProvider, this.options.IgnorePlatformInconsistencies); using (var pluginStream = LoadFileFromLocalDisk(pluginLoadContext.PluginAssemblyPath, pluginLoadContext.PluginAssemblyName)) { this.assemblyLoadStrategy = this.assemblyLoadStrategyProvider.ProvideAssemblyLoadStrategy(this.logger, pluginLoadContext, this.pluginDependencyContext); return(base.LoadFromStream(pluginStream)); // ==> AssemblyLoadContext.LoadFromStream(Stream stream); } }
public virtual async Task <Assembly> LoadPluginAssemblyAsync(IPluginLoadContext pluginLoadContext) { if (this.pluginDependencyContext != null) { throw new PrisePluginException($"Plugin {pluginLoadContext.PluginAssemblyName} was already loaded"); } this.pluginDependencyContext = await PluginDependencyContext.FromPluginAssemblyAsync( pluginLoadContext, this.hostFrameworkProvider, this.hostTypesProvider.ProvideHostTypes(), this.remoteTypesProvider.ProvideRemoteTypes(), this.runtimePlatformContext, this.depsFileProvider, this.options.IgnorePlatformInconsistencies); using (var pluginStream = await LoadFileFromLocalDiskAsync(pluginLoadContext.PluginAssemblyPath, pluginLoadContext.PluginAssemblyName)) { this.assemblyLoadStrategy = this.assemblyLoadStrategyProvider.ProvideAssemblyLoadStrategy(pluginLoadContext, this.pluginDependencyContext); return(base.LoadFromStream(pluginStream)); // ==> AssemblyLoadContext.LoadFromStream(Stream stream); } }
public virtual async Task <Assembly> LoadPluginAssemblyAsync(IPluginLoadContext pluginLoadContext) { GuardIfAlreadyLoaded(pluginLoadContext?.PluginAssemblyName); this.pluginDependencyContext = await PluginDependencyContext.FromPluginAssemblyAsync( pluginLoadContext, this.logger, this.hostFrameworkProvider, this.hostTypesProvider.ProvideHostTypes(), this.hostTypesProvider.ProvideHostAssemblies(), this.downgradableDependenciesProvider.ProvideDowngradableTypes(), this.downgradableDependenciesProvider.ProvideDowngradableAssemblies(), this.remoteTypesProvider.ProvideRemoteTypes(), this.runtimePlatformContext, this.depsFileProvider, this.options.IgnorePlatformInconsistencies); using (var pluginStream = await LoadFileFromLocalDiskAsync(pluginLoadContext.PluginAssemblyPath, pluginLoadContext.PluginAssemblyName)) { this.assemblyLoadStrategy = this.assemblyLoadStrategyProvider.ProvideAssemblyLoadStrategy(this.logger, pluginLoadContext, this.pluginDependencyContext); return(LoadAndAddToWeakReferences(pluginStream)); } }
protected virtual bool IsRemoteAssembly(AssemblyName assemblyName, IPluginDependencyContext pluginDependencyContext) => pluginDependencyContext.RemoteDependencies.Any(r => r.DependencyName.Name == assemblyName.Name );
protected virtual bool IsHostAssembly(AssemblyName assemblyName, IPluginDependencyContext pluginDependencyContext) => pluginDependencyContext.HostDependencies.Any(h => h.DependencyName.Name == assemblyName.Name );