-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enhancement Allow unload AssemblyLoadContext which contains Avalonia …
…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
- Loading branch information
Showing
30 changed files
with
727 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/App.axaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Application xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
x:Class="UnloadableAssemblyLoadContext.App" | ||
RequestedThemeVariant="Default"> | ||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> | ||
|
||
<Application.Styles> | ||
<FluentTheme /> | ||
</Application.Styles> | ||
</Application> |
23 changes: 23 additions & 0 deletions
23
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/App.axaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using Avalonia; | ||
using Avalonia.Controls.ApplicationLifetimes; | ||
using Avalonia.Markup.Xaml; | ||
|
||
namespace UnloadableAssemblyLoadContext; | ||
|
||
public partial class App : Application | ||
{ | ||
public override void Initialize() | ||
{ | ||
AvaloniaXamlLoader.Load(this); | ||
} | ||
|
||
public override void OnFrameworkInitializationCompleted() | ||
{ | ||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) | ||
{ | ||
desktop.MainWindow = new MainWindow(); | ||
} | ||
|
||
base.OnFrameworkInitializationCompleted(); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/AssemblyLoadContextH.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#region | ||
|
||
using System; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Runtime.Loader; | ||
using Avalonia; | ||
using Avalonia.Platform; | ||
using Avalonia.Styling; | ||
|
||
#endregion | ||
|
||
namespace UnloadableAssemblyLoadContext; | ||
|
||
public class AssemblyLoadContextH : AssemblyLoadContext | ||
{ | ||
private readonly AssemblyDependencyResolver _resolver; | ||
|
||
public AssemblyLoadContextH(string pluginPath, string name) : base(isCollectible: true, name: name) | ||
{ | ||
_resolver = new AssemblyDependencyResolver(pluginPath); | ||
Unloading += (sender) => | ||
{ | ||
AvaloniaPropertyRegistry.Instance.UnregisterByModule(sender.Assemblies.First().DefinedTypes); | ||
Application.Current.Styles.Remove(MainWindow.Style); | ||
AssetLoader.InvalidateAssemblyCache(sender.Assemblies.First().GetName().Name); | ||
MainWindow.Style= null; | ||
}; | ||
} | ||
|
||
protected override Assembly Load(AssemblyName assemblyName) | ||
{ | ||
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName); | ||
if (assemblyPath != null) | ||
{ | ||
if (assemblyPath.EndsWith("WinRT.Runtime.dll") || assemblyPath.EndsWith("Microsoft.Windows.SDK.NET.dll")|| assemblyPath.EndsWith("Avalonia.Controls.dll")|| assemblyPath.EndsWith("Avalonia.Base.dll")|| assemblyPath.EndsWith("Avalonia.Markup.Xaml.dll")) | ||
{ | ||
return null; | ||
} | ||
|
||
return LoadFromAssemblyPath(assemblyPath); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName) | ||
{ | ||
var libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName); | ||
if (libraryPath != null) | ||
{ | ||
return LoadUnmanagedDllFromPath(libraryPath); | ||
} | ||
|
||
return IntPtr.Zero; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/MainWindow.axaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Window xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" | ||
x:Class="UnloadableAssemblyLoadContext.MainWindow" | ||
Title="UnloadableAssemblyLoadContext"> | ||
Welcome to Avalonia! | ||
</Window> |
134 changes: 134 additions & 0 deletions
134
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/MainWindow.axaml.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Reflection; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Avalonia; | ||
using Avalonia.Controls; | ||
using Avalonia.Controls.ApplicationLifetimes; | ||
using Avalonia.Markup.Xaml; | ||
using Avalonia.Markup.Xaml.Styling; | ||
using Avalonia.Markup.Xaml.XamlIl.Runtime; | ||
using Avalonia.Platform; | ||
using Avalonia.Platform.Internal; | ||
using Avalonia.Styling; | ||
using Avalonia.Threading; | ||
using Avalonia.VisualTree; | ||
|
||
namespace UnloadableAssemblyLoadContext; | ||
|
||
public partial class MainWindow : Window | ||
{ | ||
public MainWindow() | ||
{ | ||
InitializeComponent(); | ||
} | ||
private void InitializeComponent() | ||
{ | ||
AvaloniaXamlLoader.Load(this); | ||
if (Debugger.IsAttached) | ||
{ | ||
this.AttachDevTools(); | ||
} | ||
} | ||
private PlugTool _plugTool; | ||
protected override void OnOpened(EventArgs e) | ||
{ | ||
base.OnOpened(e); | ||
test(); | ||
//Content = _plugTool.FindControl("UnloadableAssemblyLoadContextPlug.TestControl"); | ||
|
||
|
||
} | ||
public T? GetChildOfType<T>(Control control) | ||
where T : Control | ||
{ | ||
var queue = new Queue<Control>(); | ||
queue.Enqueue(control); | ||
|
||
while (queue.Count > 0) | ||
{ | ||
var currentControl = queue.Dequeue(); | ||
foreach (var child in currentControl.GetVisualChildren()) | ||
{ | ||
var childControl = child as Control; | ||
if (childControl != null) | ||
{ | ||
var childControlStyles = childControl.Styles; | ||
if (childControlStyles.Count>1) | ||
{ | ||
|
||
} | ||
queue.Enqueue(childControl); | ||
} | ||
} | ||
} | ||
|
||
return null; | ||
} | ||
protected override void OnClosed(EventArgs e) | ||
{ | ||
base.OnClosed(e); | ||
GetChildOfType<Control>(this); | ||
|
||
|
||
Thread.CurrentThread.IsBackground = false; | ||
var weakReference = _plugTool.Unload(); | ||
while (weakReference.IsAlive) | ||
{ | ||
GC.Collect(); | ||
GC.WaitForPendingFinalizers(); | ||
Thread.Sleep(100); | ||
} | ||
|
||
Console.WriteLine("Done"); | ||
|
||
|
||
} | ||
|
||
public static IStyle Style; | ||
public void test(){ | ||
|
||
//Notice : 你可以删除UnloadableAssemblyLoadContextPlug.dll所在文件夹中有关Avalonia的所有Dll,但这不是必须的 | ||
//Notice : You can delete all Dlls about Avalonia in the folder where UnloadableAssemblyLoadContextPlug.dll is located, but this is not necessary | ||
FileInfo fileInfo = new FileInfo("..\\..\\..\\..\\UnloadableAssemblyLoadContextPlug\\bin\\Debug\\net7.0\\UnloadableAssemblyLoadContextPlug.dll"); | ||
var AssemblyLoadContextH = new AssemblyLoadContextH(fileInfo.FullName,"test"); | ||
|
||
var assembly = AssemblyLoadContextH.LoadFromAssemblyPath(fileInfo.FullName); | ||
var assemblyDescriptorResolver = | ||
_plugTool=new PlugTool(); | ||
_plugTool.AssemblyLoadContextH = AssemblyLoadContextH; | ||
|
||
var styles = new Styles(); | ||
var styleInclude = new StyleInclude(new Uri("avares://UnloadableAssemblyLoadContextPlug", UriKind.Absolute)); | ||
styleInclude.Source=new Uri("ControlStyle.axaml", UriKind.Relative); | ||
styles.Add(styleInclude); | ||
Style = styles; | ||
Application.Current.Styles.Add(styles); | ||
foreach (var type in assembly.GetTypes()) | ||
{ | ||
if (type.FullName=="AvaloniaPlug.Window1") | ||
{ | ||
//创建type实例 | ||
Window instance = (Window)type.GetConstructor( new Type[0]).Invoke(null); | ||
|
||
Dispatcher.UIThread.InvokeAsync(() => | ||
{ | ||
instance.Show(); | ||
instance.Close(); | ||
|
||
}).Wait(); | ||
|
||
instance = null; | ||
|
||
//instance.Show(); | ||
} | ||
|
||
} | ||
|
||
} | ||
|
||
|
||
} |
31 changes: 31 additions & 0 deletions
31
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/PlugTool.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.Linq; | ||
using Avalonia.Controls; | ||
|
||
namespace UnloadableAssemblyLoadContext; | ||
|
||
public class PlugTool | ||
{ | ||
public AssemblyLoadContextH AssemblyLoadContextH; | ||
public WeakReference Unload() | ||
{ | ||
var weakReference = new WeakReference(AssemblyLoadContextH); | ||
AssemblyLoadContextH.Unload(); | ||
AssemblyLoadContextH = null; | ||
return weakReference; | ||
} | ||
|
||
public Control? FindControl(string type) | ||
{ | ||
var type1 = AssemblyLoadContextH.Assemblies. | ||
FirstOrDefault(x => x.GetName().Name == "UnloadableAssemblyLoadContextPlug")?. | ||
GetType(type); | ||
if (type1.IsSubclassOf(typeof(Control))) | ||
{ | ||
var constructorInfo = type1.GetConstructor( Type.EmptyTypes).Invoke(null) as Control; | ||
return constructorInfo; | ||
} | ||
|
||
return null; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/Program.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using Avalonia; | ||
|
||
namespace UnloadableAssemblyLoadContext; | ||
|
||
class Program | ||
{ | ||
// Initialization code. Don't use any Avalonia, third-party APIs or any | ||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized | ||
// yet and stuff might break. | ||
[STAThread] | ||
public static void Main(string[] args) => BuildAvaloniaApp() | ||
.StartWithClassicDesktopLifetime(args); | ||
|
||
// Avalonia configuration, don't remove; also used by visual designer. | ||
public static AppBuilder BuildAvaloniaApp() | ||
=> AppBuilder.Configure<App>() | ||
.UsePlatformDetect() | ||
.WithInterFont() | ||
.LogToTrace(); | ||
} |
11 changes: 11 additions & 0 deletions
11
samples/UnloadableAssemblyLoadContext/UnloadableAssemblyLoadContext/Styles1.axaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<Styles xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> | ||
<Design.PreviewWith> | ||
<Border Padding="20"> | ||
<!-- Add Controls for Previewer Here --> | ||
</Border> | ||
</Design.PreviewWith> | ||
|
||
<!-- Add Styles Here --> | ||
</Styles> | ||
|
Oops, something went wrong.