コード例 #1
0
        private async Task <Assembly?> LoadAssemblyByNameAsync(
            AssemblyName assemblyName,
            AssemblyLoaderContext?context)
        {
            if (_assemblyLoadContext == null)
            {
                return(null);
            }

            IAssemblyComparer comparer = GetAssemblyNameComparer(assemblyName);

            if (TryGetAlreadyLoadedAssembly(assemblyName, comparer, out var alreadyLoadedAssembly))
            {
                return(alreadyLoadedAssembly);
            }

            if (TryGetAlreadyLoadingAssembly(assemblyName, comparer, out var assemblyLoadingTask))
            {
                Debug.WriteLine($"Waiting for Loading Assembly '{assemblyName}'");

                return(await assemblyLoadingTask !.ConfigureAwait(false));
            }

            AssemblyLoaderContext contextScope = context == null
                ? new AssemblyLoaderContext(assemblyName)
                : context.NewScope(assemblyName);

            Assembly?assembly = await PerformAssemblyLoad(assemblyName, comparer, contextScope).ConfigureAwait(false);

            return(assembly);
        }
コード例 #2
0
        private async Task <Assembly?> ResolveAssembly(
            AssemblyName assemblyName,
            IAssemblyComparer comparer,
            AssemblyLoaderContext context)
        {
            if (_assemblyLoadContext == null)
            {
                return(null);
            }

            // Try loading the assembly by name (this works when the assembly is part of the bootloader, but never used explicitly)
            Assembly?assembly = _assemblyLoadContext.Load(assemblyName);

            if (assembly != null)
            {
                return(assembly);
            }

            AssemblyData?data = await _assemblyDataProvider.GetAssemblyDataAsync(assemblyName, context).ConfigureAwait(false);

            if (data == null)
            {
                Debug.WriteLine($"Failed to resolve Assembly: '{assemblyName}'");
                return(null);
            }

            var dependencies = await ResolveDependencies(assemblyName, data, context).ConfigureAwait(false);

            if (dependencies == null)
            {
                return(null);
            }

            return(_assemblyLoadContext.Load(data));
        }
コード例 #3
0
        public Assembly?GetLoadedAssemblyByName(AssemblyName assemblyName)
        {
            IAssemblyComparer comparer = GetAssemblyNameComparer(assemblyName);

            if (TryGetAlreadyLoadedAssembly(assemblyName, comparer, out var alreadyLoadedAssembly))
            {
                return(alreadyLoadedAssembly);
            }

            return(null);
        }
コード例 #4
0
        private bool TryGetAlreadyLoadingAssembly(
            AssemblyName assemblyName,
            IAssemblyComparer comparer,
            out Task <Assembly?>?assemblyLoadingTask)
        {
            var assemblyLoadingEntry = _loadingAssemblies
                                       .FirstOrDefault(kv => comparer.Equals(assemblyName, kv.Key));

            if (assemblyLoadingEntry.Key == null)
            {
                assemblyLoadingTask = null;
                return(false);
            }

            assemblyLoadingTask = assemblyLoadingEntry.Value;
            return(true);
        }
コード例 #5
0
        private bool TryGetAlreadyLoadedAssembly(
            AssemblyName assemblyName,
            IAssemblyComparer comparer,
            out Assembly?assembly)
        {
            if (_assemblyLoadContext == null)
            {
                assembly = null;
                return(false);
            }

            Assembly?loadedAssembly = _assemblyLoadContext.AllAssemblies
                                      .FirstOrDefault(a => comparer.Equals(assemblyName, a.GetName()));

            assembly = loadedAssembly;
            return(loadedAssembly != null);
        }
コード例 #6
0
        private async Task <Assembly?> PerformAssemblyLoad(
            AssemblyName assemblyName,
            IAssemblyComparer comparer,
            AssemblyLoaderContext context)
        {
            var assemblyLoadingTaskSource = new TaskCompletionSource <Assembly?>();

            if (!TryActionRepeteadly(() => _loadingAssemblies.TryAdd(assemblyName, assemblyLoadingTaskSource.Task), 5))
            {
                throw new InvalidOperationException($"Unable to Load Assembly '{assemblyName}': Concurrency error (adding)");
            }

            Debug.WriteLine($"Loading Assembly: '{assemblyName}'");

            Assembly?assembly = await ResolveAssembly(assemblyName, comparer, context).ConfigureAwait(false);

            if (assembly != null)
            {
                Debug.WriteLine($"Loaded Assembly: '{assemblyName}'");

                foreach (var assemblyLoadCallback in _onAssemblyLoad)
                {
                    await assemblyLoadCallback.Invoke(assembly).ConfigureAwait(false);
                }
            }
            else
            {
                Debug.WriteLine($"Assembly '{assemblyName}' failed to load");
            }

            assemblyLoadingTaskSource.SetResult(assembly);

            if (!TryActionRepeteadly(() => _loadingAssemblies.TryRemove(assemblyName, out var _), 5))
            {
                throw new InvalidOperationException($"Unable to Load Assembly '{assemblyName}': Concurrency error (removing)");
            }

            return(assembly);
        }