I am building a simple plugin architecture in .NET Core 3.0. I have a solution with two projects: Plugin
and WpfApp
. Here is the version of the .NET Core 3.0 SDK I have installed:
PS > dotnet --version
3.0.100-preview7-012821
Plugin
The Plugin
project is a class library project targeting .NET Standard 2.0. It references the System.Management
NuGet package version 4.5.0
and uses classes from that package. The project compiles, of course. Here is the relevant IL from the assembly showing the assembly extern
reference:
// Metadata version: v4.0.30319
.assembly extern netstandard
{
.publickeytoken = (CC 7B 13 FF CD 2D DD 51 ) // .{...-.Q
.ver 2:0:0:0
}
.assembly extern System.Management
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:0:0:0
}
WpfApp
The WpfApp
project is a WPF project targeting .NET Core 3.0. I configured the project to depend on Plugin
using Solution Explorer's Project Dependencies feature, since WpfApp
doesn't directly reference Plugin
. This ensures Plugin
always builds before WpfApp
.
WpfApp
references the System.Runtime.Loader
NuGet package version 4.3.0
in order to use its AssemblyLoadContext
class. My MainWindow
window loads the Plugin
project DLL using AssemblyLoadContext.LoadAssemblyFromFile
. WpfApp
then instantiates a MyPlugin
class from Plugin
and attempts to invoke the Invoke
method. Invoke
instantiates classes from System.Management
:
Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(@"C:\Solutions\Plugins\Plugin\bin\Debug\netstandard2.0\Plugin.dll");
object instance = assembly.CreateInstance("Plugin.MyPlugin");
instance.GetType().GetMethod("Invoke").Invoke(instance, new object[0]);
As soon as Invoke
attempts to do this, an exception is thrown:
System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'
Inner exception:
FileNotFoundException: Could not load file or assembly 'System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
What's going on here?
I expected AssemblyLoadContext
to load all these system references, but it seems I was incorrect. As far as I can tell, referencing the NuGet package does not actually copy DLLs to Plugin
's output directory but merely causes the above assembly extern
IL to be generated. This is breaking my plugin architecture because I cannot possibly know all the external .NET Core 3.0 SDK assemblies that all plugins might reference. I'd understand if it were trying to load third-party references but these are NuGet packages representing DLLs included in the .NET Core 3.0 SDK. In my case, I can guarantee they'll be on the system.
Am I doing something wrong? How can I get AssemblyLoadContext
to load these external references? Alternatively, is there any other way of getting this to work aside from copying System.Management.dll
(which I do not view as a viable solution)?
Aucun commentaire:
Enregistrer un commentaire