Browse Source
* 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 * nukepull/15258/head
committed by
GitHub
30 changed files with 720 additions and 70 deletions
@ -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> |
|||
@ -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(); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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();
|
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
@ -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(); |
|||
} |
|||
@ -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> |
|||
|
|||
@ -0,0 +1,38 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> |
|||
<ApplicationManifest>app.manifest</ApplicationManifest> |
|||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> |
|||
<IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<Compile Update="**\*.xaml.cs"> |
|||
<DependentUpon>%(Filename)</DependentUpon> |
|||
</Compile> |
|||
<AvaloniaResource Include="**\*.xaml"> |
|||
<SubType>Designer</SubType> |
|||
</AvaloniaResource> |
|||
<AvaloniaResource Include="Assets\*" /> |
|||
<AvaloniaResource Include="Assets\Fonts\*" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Folder Include="Models\"/> |
|||
<AvaloniaResource Include="Assets\**"/> |
|||
</ItemGroup> |
|||
<ImportGroup> |
|||
<Import Project="..\..\..\build\BuildTargets.targets" Condition="Exists('..\..\..\build\BuildTargets.targets')" /> |
|||
<Import Project="..\..\..\build\SourceGenerators.props" /> |
|||
</ImportGroup> |
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Base\Avalonia.Base.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<!-- This manifest is used on Windows only. |
|||
Don't remove it as it might cause problems with window transparency and embedded controls. |
|||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests --> |
|||
<assemblyIdentity version="1.0.0.0" name="AvaloniaApplication2.Desktop"/> |
|||
|
|||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> |
|||
<application> |
|||
<!-- A list of the Windows versions that this application has been tested on |
|||
and is designed to work with. Uncomment the appropriate elements |
|||
and Windows will automatically select the most compatible environment. --> |
|||
|
|||
<!-- Windows 10 --> |
|||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> |
|||
</application> |
|||
</compatibility> |
|||
</assembly> |
|||
@ -0,0 +1,12 @@ |
|||
<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> |
|||
|
|||
<StyleInclude Source="TestControl.axaml"></StyleInclude> |
|||
</Styles> |
|||
|
|||
@ -0,0 +1,9 @@ |
|||
namespace AvaloniaPlug; |
|||
|
|||
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.
|
|||
private static string test = "23"; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<Styles xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:controls="using:UnloadableAssemblyLoadContextPlug"> |
|||
<Design.PreviewWith> |
|||
<controls:TestControl /> |
|||
</Design.PreviewWith> |
|||
|
|||
<Style Selector="controls|TestControl"> |
|||
<!-- Set Defaults --> |
|||
<Setter Property="Template"> |
|||
<ControlTemplate> |
|||
<TextBlock Text="Templated Control" /> |
|||
</ControlTemplate> |
|||
</Setter> |
|||
</Style> |
|||
</Styles> |
|||
|
|||
@ -0,0 +1,10 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Controls.Primitives; |
|||
|
|||
namespace UnloadableAssemblyLoadContextPlug; |
|||
|
|||
public class TestControl : TemplatedControl |
|||
{ |
|||
} |
|||
|
|||
@ -0,0 +1,51 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
<PropertyGroup> |
|||
<TargetFramework>net7.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport> |
|||
<ApplicationManifest>app.manifest</ApplicationManifest> |
|||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault> |
|||
<AssemblyName>UnloadableAssemblyLoadContextPlug</AssemblyName> |
|||
<RootNamespace>UnloadableAssemblyLoadContextPlug</RootNamespace> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<AvaloniaResource Include="Assets\**"/> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Update="**\*.xaml.cs"> |
|||
<DependentUpon>%(Filename)</DependentUpon> |
|||
</Compile> |
|||
<AvaloniaResource Include="**\*.xaml"> |
|||
<SubType>Designer</SubType> |
|||
</AvaloniaResource> |
|||
<AvaloniaResource Include="Assets\*" /> |
|||
<AvaloniaResource Include="Assets\Fonts\*" /> |
|||
</ItemGroup> |
|||
|
|||
<ImportGroup> |
|||
<Import Project="..\..\..\build\BuildTargets.targets" Condition="Exists('..\..\..\build\BuildTargets.targets')" /> |
|||
<Import Project="..\..\..\build\SourceGenerators.props" /> |
|||
</ImportGroup> |
|||
|
|||
|
|||
|
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" /> |
|||
<ProjectReference Condition="'$(Configuration)' == 'Debug'" Include="..\..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" /> |
|||
<ProjectReference Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\Avalonia.Markup.Xaml.Loader.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
|
|||
<ItemGroup> |
|||
<UpToDateCheckInput Remove="Views\MainWindow.axaml" /> |
|||
</ItemGroup> |
|||
|
|||
|
|||
|
|||
</Project> |
|||
@ -0,0 +1,12 @@ |
|||
<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" |
|||
xmlns:avaloniaPlug="clr-namespace:AvaloniaPlug" |
|||
xmlns:unloadableAssemblyLoadContextPlug="clr-namespace:UnloadableAssemblyLoadContextPlug" |
|||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
|||
x:Class="UnloadableAssemblyLoadContextPlug.Window1" |
|||
x:DataType="unloadableAssemblyLoadContextPlug:Window1ViewModel" |
|||
Title="Window1"> |
|||
<TextBlock Text="{Binding Text }" HorizontalAlignment="Center" VerticalAlignment="Center" /> |
|||
</Window> |
|||
@ -0,0 +1,22 @@ |
|||
using System.Diagnostics; |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Markup.Xaml; |
|||
using AvaloniaPlug; |
|||
|
|||
namespace UnloadableAssemblyLoadContextPlug; |
|||
|
|||
public partial class Window1 : Window |
|||
{ |
|||
public Window1() |
|||
{ |
|||
InitializeComponent(); |
|||
DataContext=new Window1ViewModel(); |
|||
} |
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
|
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
|
|||
|
|||
namespace UnloadableAssemblyLoadContextPlug; |
|||
|
|||
public partial class Window1ViewModel |
|||
{ |
|||
public string Text { get; set; } = "12"; |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> |
|||
<!-- This manifest is used on Windows only. |
|||
Don't remove it as it might cause problems with window transparency and embedded controls. |
|||
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests --> |
|||
<assemblyIdentity version="1.0.0.0" name="AvaloniaPlug.Desktop"/> |
|||
|
|||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> |
|||
<application> |
|||
<!-- A list of the Windows versions that this application has been tested on |
|||
and is designed to work with. Uncomment the appropriate elements |
|||
and Windows will automatically select the most compatible environment. --> |
|||
|
|||
<!-- Windows 10 --> |
|||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> |
|||
</application> |
|||
</compatibility> |
|||
</assembly> |
|||
Loading…
Reference in new issue