Search code examples
c#.net-corereflection.net-6.0.net-assembly

Load assemblies put in the "runtimes" directory in .net when loading plugins with AssemblyLoadContext


I have an application (WPF with .net 6 on Windows) that can load plugins using AssemblyLoadContext. The plugins are built .net 6 class libraries.

In one plugin i reference a windows-specific dll that in turn reference System.Drawing.Common.dll.

The build output is put in: \bin\x86\Debug\net6.0-windows and contains System.Drawing.Common which is 174 KB. Also there is a runtimes-directory: \bin\x86\Debug\net6.0-windows\runtimes\win\lib\net6.0 which contains System.Drawing.Common.dll which is 511 KB and I gather is not cross platform and windows only.

I load the plugin from the application with:

    var assemblies = Directory
                .GetFiles(pluginBuildOutputPath, "*.dll", SearchOption.TopDirectoryOnly)
                .Select(dll => loadContext.LoadFromAssemblyPath(dll))
                .ToList();

Which of course only contains the generic System.Drawing.Common as i search for TopDirectoryOnly. I need it to load the windows-version of the dll, But I cannot recursively load all dll:s in bin/debug, as it contains two of the same dll:s.

What should my approach be?

  1. Build the plugin in some way in order to make the root bin/Debug contain all dll:s I need, so I need not load the runtimes directory?

This is what the plugin csproj-file top-level PropertyGroup contains:

  <PropertyGroup>
    <TargetFramework>net6.0-windows</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <Platforms>x86</Platforms>
      <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>     
  </PropertyGroup>
  1. Or can I load the assemblies in a smarter way?

This is a generic problem, so System.Drawing.Common.dll is only one example of this behavior. Cross platform support is not needed, so it is OK to enforce win-only dll:s.

Thanks for your time!


Solution

  • You need to specify exact runtime in which you want to build it. You can do it in at least two ways. Define RuntimeIdentifiers in csproj:

    <RuntimeIdentifier>win</RuntimeIdentifier>

    (you should verify all available runtime identifers here)

    or add this information directly to build command:

    dotnet build [-r|--runtime <RUNTIME_IDENTIFIER>]