I am working on an ASP.NET Core API that is extensible with Plug-Ins. Because the Plug-In Assemblies need to be unloadable, I've started loading them into separate, collectible, AssemblyLoadContexts.
The Implementation basically looks like this:
// Creating a new Context for the Plugin.
AssemblyLoadContext context = new AssemblyLoadContext(directoryInfo.FullName, true);
...
// Loading every Assembly the Plugin uses into the Context.
Assembly assembly = context.LoadFromAssemblyPath(fileInfo.FullName);
...
// Creating AssemblyCatalogs with the Assemblies.
AssemblyCatalog assemblyCatalog = new AssemblyCatalog(assembly);
This works and I can use the Assemblies normally. However, the AssemblyCatalogs all have unpopulated Parts Properties and thus will not compose.
Now, if I load the Assemblies into the Default Context (AssemblyLoadContext.Default
), everything works as expected, except the unloading of course.
What am I missing? Thanks for pointing me in the right direction :)
Okay, turns out I've made a mistake. My Plug-In Project had CopyLocalLockFileAssemblies
set to true
and because of this, copied the NuGet dependencies to the output directory. Since I would then just copy the output to the directory the API loads its Plug-Ins from, the API tried to load these referenced libraries as well. Now, both the API and Plug-In Project reference System.ComponentModel.Composition
and - long story short - the DLL was loaded twice, in different versions. The API was using 6.0.0
and the Plug-In was using 4.0.0
.
Because of this, the attribute comparison (MEF finds its exports by looking for the ExportAttribute
) would later fail which is why the AssemblyCatalog
was not able to find the Exports.