-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamically load and uninstall a library containing Avalonia components #13935
Comments
…content #13935 (#13974) * Try fix #13935 * Fix * Fix * add sample * Fix * try load Style by reflection * try * Fixed an error when registering properties when uninstalling assemblies * Allowed to delete the IAssemblyDescriptorResolver StandardAssetLoader _assemblyNameCache * Resolving merge conflicts * Fix * Add exegesis * optimize * fix * Resolving merge conflicts * nuke
Edit: Opened separate issue #17129. I would not consider this done for anything but the most trivial application at this point. There are still some things that will keep an assembly loaded forever, even when adding the same Unloading handler as the sample. The biggest issue is Observables. We need a way to disconnect all observable listeners belonging to an assembly. For example, lets take a rather trivial library like AvaloniaProgressRing, which is basically all implemented using animations. The issue is that the animation system itself connects to Observables that get stuck even though the whole module UserControl, which contains the spinner, is removed from the window before unloading the AssemblyLoadContext. Here is what I can see in dotMemory some time after the unload happens: Another slightly tangential issue that I am encountering is that if I ignore the memory leak I actually can't even reload any of the module's assemblies later because all Avalonia/src/Avalonia.Base/Platform/Internal/AssemblyDescriptorResolver.cs Lines 28 to 29 in b8d8fda
The problem is that it just gets a list of all assemblies in the AppDomain and finds the first assembly with the requested name. Problem being that the half-unloaded assembly is the first on that it finds. Since AssemblyDescriptorResolver is an internal Avalonia class that I can't extend, the only way I was able to work around the problem is using Harmony to hot-patch the GetAssembly method with a version that resolves assemblies through the correct AssemblyLoadContext. This is obviously a very bad and fragile workaround, so it would be nice to get the module to fully unload in the first place. |
Do you mean in the sample code 'Assemblies.First()'? You can call Assemblies multiple times or iterate over all Assemblies calls to unload Listening to all Observables seems to be possible by reimplementing the corresponding interface and creating a new class The current solution is indeed fragile and provides only a minimal offload capability, and it seems complex to implement automatic offloading. |
I understood what you meant in the sample and I did call those functions for all assemblies loaded through the AssemblyLoadContext. The problem is that there are many cases where 3rd party libraries or even Avalonia internals set up observers but never disconnect them. Just today issue #17139 shows it happening with the Avalonia internal animation system, which is out of my control. |
Describe the bug
I want to dynamically load and uninstall a library containing Avalonia components in an Avalonia project, but I notice that Avalonia components seem to register a lot of things in the main project, is there any way I can remove these registrations so that they can be uninstalled
If don't create Avalonia controls from the library, everything is fine
To Reproduce
//dll
Expected behavior
can be uninstalled
Screenshots
Environment
Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: