Skip to content

Commit

Permalink
feat: Load exported assembly in separated AssemblyLoadContext (#192)
Browse files Browse the repository at this point in the history
* Load exported assembly in separated AssemblyLoadContext

* Fix warning

---------

Co-authored-by: Manuel Leßmann <MLessmann@dspace.de>
  • Loading branch information
mlessmann and Manuel Leßmann committed Sep 18, 2023
1 parent 06d64d2 commit a240d61
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 20 deletions.
44 changes: 29 additions & 15 deletions src/dscom.client/AssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
// 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.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Reflection;
using System.Runtime.Loader;

namespace dSPACE.Runtime.InteropServices;

Expand All @@ -21,46 +22,59 @@ namespace dSPACE.Runtime.InteropServices;
/// </summary>
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;
Expand Down
9 changes: 4 additions & 5 deletions src/dscom.client/Program.cs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit a240d61

Please sign in to comment.