From a240d61e0e056d6bda118936f4ff16c5d2e6de36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Le=C3=9Fmann?= Date: Mon, 18 Sep 2023 14:23:50 +0200 Subject: [PATCH] feat: Load exported assembly in separated AssemblyLoadContext (#192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Load exported assembly in separated AssemblyLoadContext * Fix warning --------- Co-authored-by: Manuel Leßmann --- src/dscom.client/AssemblyResolver.cs | 44 ++++++++++++++++++---------- src/dscom.client/Program.cs | 9 +++--- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/dscom.client/AssemblyResolver.cs b/src/dscom.client/AssemblyResolver.cs index 6c53ab7..0b0a50b 100644 --- a/src/dscom.client/AssemblyResolver.cs +++ b/src/dscom.client/AssemblyResolver.cs @@ -1,11 +1,11 @@ // Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,6 +13,7 @@ // limitations under the License. using System.Reflection; +using System.Runtime.Loader; namespace dSPACE.Runtime.InteropServices; @@ -21,46 +22,59 @@ namespace dSPACE.Runtime.InteropServices; /// internal sealed class AssemblyResolver : IDisposable { + private readonly AssemblyLoadContext _context; private bool _disposedValue; internal AssemblyResolver(TypeLibConverterOptions options) { Options = options; - AppDomain.CurrentDomain.AssemblyResolve += ResolveEventHandler; + _context = new AssemblyLoadContext("dscom", true); + _context.Resolving += Context_Resolving; } - public TypeLibConverterOptions Options { get; } - - private Assembly? ResolveEventHandler(object? sender, ResolveEventArgs args) + private Assembly? Context_Resolving(AssemblyLoadContext context, AssemblyName name) { - var name = args.Name; - var fileNameWithoutExtension = new AssemblyName(name).Name; + var dir = Path.GetDirectoryName(Options.Assembly); + + var asmPaths = Options.ASMPath; + if (Directory.Exists(dir)) + { + asmPaths = asmPaths.Prepend(dir).ToArray(); + } - foreach (var path in Options.ASMPath) + foreach (var path in asmPaths) { - var dllToLoad = Path.Combine(path, $"{fileNameWithoutExtension}.dll"); + var dllToLoad = Path.Combine(path, $"{name.Name}.dll"); if (File.Exists(dllToLoad)) { - return Assembly.LoadFrom(dllToLoad); + return _context.LoadFromAssemblyPath(dllToLoad); } - var exeToLoad = Path.Combine(path, $"{fileNameWithoutExtension}.exe"); + var exeToLoad = Path.Combine(path, $"{name.Name}.exe"); if (File.Exists(exeToLoad)) { - return Assembly.LoadFrom(exeToLoad); + return _context.LoadFromAssemblyPath(exeToLoad); } } return null; } + public Assembly LoadAssembly(string path) + { + return _context.LoadFromAssemblyPath(path); + } + + public TypeLibConverterOptions Options { get; } + private void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { - AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= ResolveEventHandler; + _context.Resolving -= Context_Resolving; + _context.Unload(); } _disposedValue = true; diff --git a/src/dscom.client/Program.cs b/src/dscom.client/Program.cs index 5710d20..7b5ec88 100644 --- a/src/dscom.client/Program.cs +++ b/src/dscom.client/Program.cs @@ -1,11 +1,11 @@ // Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,7 +16,6 @@ using System.CommandLine.NamingConventionBinder; using System.CommandLine.Parsing; using System.Diagnostics; -using System.Reflection; using System.Runtime.InteropServices; namespace dSPACE.Runtime.InteropServices; @@ -161,7 +160,7 @@ private static void ConfigureTLBExportHandler(Command tlbexportCommand) throw new FileNotFoundException($"File {options.Assembly} not found."); } - var assembly = Assembly.LoadFrom(options.Assembly); + var assembly = assemblyResolver.LoadAssembly(options.Assembly); var typeLibConverter = new TypeLibConverter(); var nameResolver = options.Names.Any() ? NameResolver.Create(options.Names) : NameResolver.Create(assembly); var typeLib = typeLibConverter.ConvertAssemblyToTypeLib(assembly, options, new TypeLibExporterNotifySink(options, nameResolver));