My goal is to create a plugin type structure where my net core 2.0 library attempts to load an unknown (until runtime) type by reflecting through libraries in a folder.
Some of these types may require platform specific implementations.
I've attempted this by dynamically loading a .net framework 4.6.1 library (which in turn depends on System.Windows.Forms
) but when the code attempts to invoke a method on the successfully constructed type I receive the following exception:
Could not load file or assembly 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. (Exception from HRESULT: 0x80131058)
Reading MSDN it suggests that the dependant System.Windows.Forms.dll
must be being loaded into the wrong context?
First question, is there something simple I need to change to get this to work?
Secondly, is this sort of thing even possible? (mixing core with platform specific libraries)
Is there a better way to be doing this that I'm unaware of? Google is turning up decidedly limited documentation.
No, loading .Net Framework assemblies from .Net Core won't work.
Windows Forms and WPF in particular will forever remain in the .Net Framework as Windows Universal applications have become the new UI creed. Anything that relies on platform-specific features will also be excluded. - Ben Morris
.Net Core and .Net Framework assembly are different and can't interact with each other.
Thus, your plugin system can only load .Net Core or .Net Standard assemblies. If you really need .Net Framework support (or other languages), you could interact with the plugins via Process.Start()
and passing arguments via stdin/runtime arguments.
I suggest initially loading up all the DLL libraries. Then invoke methods after all the DLLs have been loaded.
If you get the error message "Could not load file or assembly ***" find and add that DLL library to the DLL library folder.
The next time you compile and run the app, it will load the missing library and should not complain when you invoke the method.
I have successfully done this. Paste your code for more advice.
The .NET Framework supported this via the Global Assembly Cache (GAC). The .NET Framework knew to look at the GAC and follow any Assembly redirects and load up the latest installed compatible version of the assembly needed.
As far as I know, this isn't the case with .NET Core. The closest you can get to it is using Framework Dependent Deployment.
I am not sure what happens when you try to load a .NET Framework assembly in a .NET Core environment, but I do not think it is supported. For example, I believe that System.Windows.Forms isn't part of .NET Core or .NET Standard 2.0. So I guess my answer you your question is no. This post by Scott Hanselman might help you understand the issue better. .NET Standard exists to allow you to build libraries that can run on .NET Core OR .NET Framework OR Xamarin, each of those being a separate runtime.
Libraries that need to work on both .net core & .net framework have to explicitly be compiled to do so (via .NET Standard which targets the common subset). The runtimes are basically different, and incompatible. Here is another link that lists some of the incompatibilities you have to overcome : docs.microsoft.com/en-us/dotnet/core/porting/libraries ...Only .NET standard libraries can be loaded in both runtimes. You will be able to dynamically load .net core & .net standard libraries, but not .NET framework libraries since the code could use functionality not supported by .NET core.
You can load assemblies from disk, however, you will face a few issues.
Just because it is compatible doesn't make it the right assembly, you need the right version as well
You open a major security issue as someone could inject a DLL that is not "yours"
You may need to load dependent assemblies in the right order.
Lucky for you there is already a solution for you that you can implement have a look at the various dependency injection frameworks, in Core, when you deploy your application and have a look at the [Application-Name].deps.json, this is a text file that informs the runtime what to load.
Updating a text file is easy, the rest is framework magic ;-)
User contributions licensed under CC BY-SA 3.0