Пример #1
0
        static void ExecuteAndUnload <T>(string modulePath, string resolvePath, Action <T> action, out WeakReference alcWeakRef) where T : class
        {
            // Create the unloadable HostAssemblyLoadContext
            var alc = new ModuleAssemblyLoadContext(resolvePath);

            // Load System.ComponentModel.TypeDescriptor to the ALC beforehand,
            // as otherwise the internal caches in it will block unloading the ALC: https://github.com/dotnet/coreclr/issues/26271
            // The netstandard assembly shim also needs to be loaded explicitly for the TypeDescriptor to be loaded.
            var typeDescriptorAssemblyPath = typeof(TypeDescriptor).Assembly.Location;

            alc.LoadFromAssemblyPath(typeDescriptorAssemblyPath);
            var netstandardShimAssemblyPath = Path.Combine(Path.GetDirectoryName(typeDescriptorAssemblyPath), "netstandard.dll");

            alc.LoadFromAssemblyPath(netstandardShimAssemblyPath);

            // Create a weak reference to the AssemblyLoadContext that will allow us to detect
            // when the unload completes.
            alcWeakRef = new WeakReference(alc);

            // Load the plugin assembly into the HostAssemblyLoadContext.
            // NOTE: the assemblyPath must be an absolute path.
            Assembly a = alc.LoadFromAssemblyPath(modulePath);

            var assemblyResolverTool = new AssemblyResolverTool();

            assemblyResolverTool.dependencyContext = DependencyContext.Load(a);

            assemblyResolverTool.assemblyResolver = new CompositeCompilationAssemblyResolver
                                                        (new ICompilationAssemblyResolver[]
            {
                new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(modulePath)),
                new ReferenceAssemblyPathResolver(),
                new PackageCompilationAssemblyResolver()
            });

            alc.Resolving += assemblyResolverTool.OnResolving;

            var module = ResolveTool.ResolveInstance <T>(a);

            action(module);

            // This initiates the unload of the HostAssemblyLoadContext. The actual unloading doesn't happen
            // right away, GC has to kick in later to collect all the stuff.
            alc.Resolving -= assemblyResolverTool.OnResolving;
            alc.Unload();
        }
        static async Task ExecuteAndUnload <T>(string modulePath, string resolvePath, Func <T, Task> action, TaskCompletionSource <WeakReference> tcs) where T : class
        {
            try
            {
                var alc = new ModuleAssemblyLoadContext(resolvePath);

                var typeDescriptorAssemblyPath = typeof(TypeDescriptor).Assembly.Location;
                alc.LoadFromAssemblyPath(typeDescriptorAssemblyPath);
                var netstandardShimAssemblyPath = Path.Combine(Path.GetDirectoryName(typeDescriptorAssemblyPath), "netstandard.dll");
                alc.LoadFromAssemblyPath(netstandardShimAssemblyPath);

                var alcWeakRef = new WeakReference(alc);

                Assembly a = alc.LoadFromAssemblyPath(modulePath);

                var assemblyResolverTool = new AssemblyResolverTool
                {
                    dependencyContext = DependencyContext.Load(a),

                    assemblyResolver = new CompositeCompilationAssemblyResolver
                                           (new ICompilationAssemblyResolver[]
                    {
                        new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(modulePath)),
                        new ReferenceAssemblyPathResolver(),
                        new PackageCompilationAssemblyResolver()
                    })
                };

                alc.Resolving += assemblyResolverTool.OnResolving;

                var module = ResolveTool.ResolveInstance <T>(a);

                await action(module);

                alc.Resolving -= assemblyResolverTool.OnResolving;
                alc.Unload();

                tcs.TrySetResult(alcWeakRef);
            }
            catch (Exception ex)
            {
                tcs.TrySetException(ex);
            }
        }