Skip to content

Commit

Permalink
Finished AppDomain-wide hot reload support
Browse files Browse the repository at this point in the history
Now `AvaloniaHotReloadExtensions` uses new AppDomain-wide `IHotReloadContext` out of the box.

Closes #7
  • Loading branch information
Kir-Antipov committed May 31, 2024
1 parent 54850b6 commit 4ec8f71
Showing 1 changed file with 33 additions and 23 deletions.
56 changes: 33 additions & 23 deletions src/HotAvalonia.Extensions/AvaloniaHotReloadExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace HotAvalonia
using global::System;
using global::System.Diagnostics.CodeAnalysis;
using global::System.IO;
using global::System.Reflection;
using global::System.Runtime.CompilerServices;
using global::Avalonia;

Expand All @@ -50,8 +51,8 @@ internal static class AvaloniaHotReloadExtensions
/// <summary>
/// A mapping between Avalonia <see cref="Application"/> instances and their associated hot reload context.
/// </summary>
private static readonly ConditionalWeakTable<Application, AvaloniaHotReloadContext> s_apps =
new ConditionalWeakTable<Application, AvaloniaHotReloadContext>();
private static readonly ConditionalWeakTable<Application, IHotReloadContext> s_apps =
new ConditionalWeakTable<Application, IHotReloadContext>();

/// <summary>
/// Enables hot reload functionality for the given Avalonia application.
Expand All @@ -61,45 +62,43 @@ internal static class AvaloniaHotReloadExtensions
public static void EnableHotReload(this Application app, [CallerFilePath] string? appFilePath = null)
{
_ = app ?? throw new ArgumentNullException(nameof(app));
_ = appFilePath ?? throw new ArgumentNullException(nameof(appFilePath));

if (!s_apps.TryGetValue(app, out AvaloniaHotReloadContext? context))
if (!s_apps.TryGetValue(app, out IHotReloadContext? context))
{
string appXamlFilePath = SourceCodeFileNameToXamlFileName(appFilePath);
if (!File.Exists(appXamlFilePath))
throw new ArgumentException("The corresponding XAML file could not be found.", nameof(appFilePath));
if (!string.IsNullOrEmpty(appFilePath) && !File.Exists(appFilePath))
throw new FileNotFoundException("The corresponding XAML file could not be found.", appFilePath);

context = AvaloniaHotReloadContext.FromControl(app, appXamlFilePath);
if (!string.IsNullOrEmpty(appFilePath))
AvaloniaProjectLocator.AddHint(app.GetType(), appFilePath);

context = AvaloniaHotReloadContext.FromAppDomain(AppDomain.CurrentDomain);
s_apps.Add(app, context);
}

context.EnableHotReload();
}

/// <summary>
/// Disables hot reload functionality for the given Avalonia application.
/// Enables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be disabled.</param>
public static void DisableHotReload(this Application app)
/// <param name="app">The Avalonia application instance for which hot reload should be enabled.</param>
/// <param name="projectPathResolver">The callback function capable of resolving a project path for a given assembly.</param>
public static void EnableHotReload(this Application app, Func<Assembly, string?> projectPathResolver)
{
_ = app ?? throw new ArgumentNullException(nameof(app));

if (s_apps.TryGetValue(app, out AvaloniaHotReloadContext? context))
context.DisableHotReload();
AvaloniaProjectLocator.AddHint(projectPathResolver);
EnableHotReload(app, string.Empty);
}

/// <summary>
/// Converts the source code file name to its associated XAML file name.
/// Disables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="sourceCodeFileName">The source code file name to be converted.</param>
/// <returns>The associated XAML file name.</returns>
private static string SourceCodeFileNameToXamlFileName(string sourceCodeFileName)
/// <param name="app">The Avalonia application instance for which hot reload should be disabled.</param>
public static void DisableHotReload(this Application app)
{
string xamlFileName = Path.Combine(
Path.GetDirectoryName(sourceCodeFileName),
Path.GetFileNameWithoutExtension(sourceCodeFileName));
_ = app ?? throw new ArgumentNullException(nameof(app));

return Path.HasExtension(xamlFileName) ? xamlFileName : sourceCodeFileName;
if (s_apps.TryGetValue(app, out IHotReloadContext? context))
context.DisableHotReload();
}
}
}
Expand All @@ -108,6 +107,7 @@ namespace HotAvalonia
{
using global::System.Diagnostics;
using global::System.Diagnostics.CodeAnalysis;
using global::System.Reflection;
using global::Avalonia;

/// <summary>
Expand All @@ -126,6 +126,16 @@ public static void EnableHotReload(this Application app, string? appFilePath = n
{
}

/// <summary>
/// Enables hot reload functionality for the given Avalonia application.
/// </summary>
/// <param name="app">The Avalonia application instance for which hot reload should be enabled.</param>
/// <param name="projectPathResolver">The callback function capable of resolving a project path for a given assembly.</param>
[Conditional("DEBUG")]
public static void EnableHotReload(this Application app, Func<Assembly, string?> projectPathResolver)
{
}

/// <summary>
/// Disables hot reload functionality for the given Avalonia application.
/// </summary>
Expand Down

0 comments on commit 4ec8f71

Please sign in to comment.