예제 #1
0
        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));
        }
예제 #2
0
        protected virtual ValueOrProceed <AssemblyFromStrategy> LoadFromRemote(string initialPluginLoadDirectory, AssemblyName assemblyName)
        {
            var assemblyFileName = $"{assemblyName.Name}.dll";

            if (this.fileSystemUtilities.DoesFileExist(Path.Combine(initialPluginLoadDirectory, assemblyFileName)))
            {
                return(LoadDependencyFromLocalDisk(initialPluginLoadDirectory, assemblyFileName));
            }
            return(ValueOrProceed <AssemblyFromStrategy> .Proceed());
        }
예제 #3
0
        protected virtual ValueOrProceed <IntPtr> LoadUnmanagedFromDefault(string initialPluginLoadDirectory, string unmanagedDllName)
        {
            var resolution = base.LoadUnmanagedDll(unmanagedDllName);

            if (resolution == default(IntPtr))
            {
                return(ValueOrProceed <IntPtr> .Proceed());
            }

            return(ValueOrProceed <IntPtr> .FromValue(resolution, false));
        }
예제 #4
0
        protected virtual ValueOrProceed <string> LoadUnmanagedFromRemote(string initialPluginLoadDirectory, string unmanagedDllName)
        {
            var assemblyFileName = $"{unmanagedDllName}.dll";
            var pathToDependency = Path.Combine(initialPluginLoadDirectory, assemblyFileName);

            if (this.fileSystemUtilities.DoesFileExist(pathToDependency))
            {
                return(ValueOrProceed <string> .FromValue(pathToDependency, false));
            }
            return(ValueOrProceed <string> .FromValue(String.Empty, true));
        }
예제 #5
0
        protected virtual ValueOrProceed <AssemblyFromStrategy> LoadDependencyFromLocalDisk(string directory, string assemblyFileName)
        {
            var dependency = this.fileSystemUtilities.ReadDependencyFileFromDisk(directory, assemblyFileName);

            if (dependency == null)
            {
                return(ValueOrProceed <AssemblyFromStrategy> .Proceed());
            }

            return(ValueOrProceed <AssemblyFromStrategy> .FromValue(AssemblyFromStrategy.Releasable(Assembly.Load(this.fileSystemUtilities.ToByteArray(dependency))), false));
        }
예제 #6
0
        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);
        }
예제 #7
0
        // <summary>
        /// This override includes the netcore 3.0 resolver
        /// </summary>
        /// <param name="assemblyName"></param>
        /// <returns></returns>
        protected ValueOrProceed <AssemblyFromStrategy> LoadFromDependencyContext(string initialPluginLoadDirectory, AssemblyName assemblyName)
        {
            var assemblyPath = this.resolver.ResolveAssemblyToPath(assemblyName);

            if (!String.IsNullOrEmpty(assemblyPath) && this.fileSystemUtilities.DoesFileExist(assemblyPath))
            {
                return(ValueOrProceed <AssemblyFromStrategy> .FromValue(AssemblyFromStrategy.Releasable(LoadFromAssemblyPath(assemblyPath)), false));
            }

            if (IsResourceAssembly(assemblyName))
            {
                foreach (var resourceDependency in this.pluginDependencyContext.PluginResourceDependencies)
                {
                    var resourcePath = Path.Combine(resourceDependency.Path, assemblyName.CultureName, assemblyName.Name + ".dll");
                    if (this.fileSystemUtilities.DoesFileExist(resourcePath))
                    {
                        return(ValueOrProceed <AssemblyFromStrategy> .FromValue(AssemblyFromStrategy.Releasable(LoadFromAssemblyPath(resourcePath)), false));
                    }
                }

                // Do not proceed probing
                return(ValueOrProceed <AssemblyFromStrategy> .FromValue(null, false));
            }

            var pluginDependency = this.pluginDependencyContext.PluginDependencies.FirstOrDefault(d => d.DependencyNameWithoutExtension == assemblyName.Name);

            if (pluginDependency != null)
            {
                var dependency = this.pluginDependencyResolver.ResolvePluginDependencyToPath(initialPluginLoadDirectory, pluginDependency, this.pluginDependencyContext.AdditionalProbingPaths);
                if (dependency != null)
                {
                    return(ValueOrProceed <AssemblyFromStrategy> .FromValue(AssemblyFromStrategy.Releasable(LoadFromStream(dependency)), false));
                }
            }

            var localFile = Path.Combine(initialPluginLoadDirectory, assemblyName.Name + ".dll");

            if (this.fileSystemUtilities.DoesFileExist(localFile))
            {
                return(ValueOrProceed <AssemblyFromStrategy> .FromValue(AssemblyFromStrategy.Releasable(LoadFromAssemblyPath(localFile)), false));
            }

            return(ValueOrProceed <AssemblyFromStrategy> .Proceed());
        }
예제 #8
0
        /// <summary>
        /// This override includes the netcore 3.0 resolver
        /// </summary>
        /// <param name="unmanagedDllName"></param>
        /// <returns></returns>
        protected ValueOrProceed <string> LoadUnmanagedFromDependencyContext(string initialPluginLoadDirectory, string unmanagedDllName)
        {
            string libraryPath = this.resolver.ResolveUnmanagedDllToPath(unmanagedDllName);

            if (!String.IsNullOrEmpty(libraryPath))
            {
                string runtimeCandidate = null;
                if (this.nativeDependencyLoadPreference == NativeDependencyLoadPreference.PreferInstalledRuntime)
                {
                    // Prefer loading from runtime folder
                    runtimeCandidate = this.pluginDependencyResolver.ResolvePlatformDependencyPathToRuntime(this.pluginPlatformVersion, libraryPath);
                }

                return(ValueOrProceed <string> .FromValue(runtimeCandidate ?? libraryPath, false));
            }

            var unmanagedDllNameWithoutFileExtension = Path.GetFileNameWithoutExtension(unmanagedDllName);
            var platformDependency = this.pluginDependencyContext.PlatformDependencies.FirstOrDefault(d => d.DependencyNameWithoutExtension == unmanagedDllNameWithoutFileExtension);

            if (platformDependency != null)
            {
                var pathToDependency = this.pluginDependencyResolver.ResolvePlatformDependencyToPath(initialPluginLoadDirectory, platformDependency, this.pluginDependencyContext.AdditionalProbingPaths);
                if (!String.IsNullOrEmpty(pathToDependency))
                {
                    string runtimeCandidate = null;
                    if (this.nativeDependencyLoadPreference == NativeDependencyLoadPreference.PreferInstalledRuntime)
                    {
                        // Prefer loading from runtime folder
                        runtimeCandidate = this.pluginDependencyResolver.ResolvePlatformDependencyPathToRuntime(this.pluginPlatformVersion, pathToDependency);
                    }

                    return(ValueOrProceed <string> .FromValue(runtimeCandidate ?? pathToDependency, false));
                }
            }

            return(ValueOrProceed <string> .FromValue(String.Empty, true));
        }
예제 #9
0
        protected virtual ValueOrProceed <RuntimeAssemblyShim> LoadFromDefaultContext(string initialPluginLoadDirectory, AssemblyName assemblyName)
        {
            try
            {
                var assemblyShim = this.runtimeDefaultAssemblyLoadContext.LoadFromDefaultContext(assemblyName);
                if (assemblyShim != null)
                {
                    return(ValueOrProceed <RuntimeAssemblyShim> .FromValue(assemblyShim, false));
                }
            }
            catch (FileNotFoundException) { } // This can happen if the plugin uses a newer version of a package referenced in the host

            var hostAssembly = this.pluginDependencyContext.HostDependencies.FirstOrDefault(h => h.DependencyName.Name == assemblyName.Name);

            if (hostAssembly != null && !hostAssembly.AllowDowngrade)
            {
                if (!hostAssembly.AllowDowngrade)
                {
                    throw new AssemblyLoadingException($"Plugin Assembly reference {assemblyName.Name} with version {assemblyName.Version} was requested but not found in the host. The version from the host is {hostAssembly.DependencyName.Version}. Possible version mismatch. Please downgrade your plugin or add {assemblyName.Name} to downgradableHostAssemblies.");
                }
            }

            return(ValueOrProceed <RuntimeAssemblyShim> .Proceed());
        }