mirror of
https://github.com/AlexMacocian/TrailBlazr.git
synced 2026-07-15 15:20:00 +00:00
Implement IDisposable on Views and ViewModels
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>0.2.9</Version>
|
||||
<Version>0.3.0</Version>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<DynamicComponent Type="@this.CurrentViewType" Parameters="@this.CurrentParameters" />
|
||||
<CascadingValue Value="this">
|
||||
<DynamicComponent Type="@this.CurrentViewType" Parameters="@this.CurrentParameters" />
|
||||
</CascadingValue>
|
||||
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using TrailBlazr.Models
|
||||
@using TrailBlazr.Services
|
||||
@using TrailBlazr.Views
|
||||
@implements IDisposable
|
||||
@code {
|
||||
[Inject]
|
||||
public required IViewManager ViewManager { get; init; }
|
||||
@@ -41,4 +45,12 @@
|
||||
this.Logger.LogError(ex, "Error changing view to {newView}", request.ViewType.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.ViewManager is not null)
|
||||
{
|
||||
this.ViewManager.ShowViewRequested -= this.UpdateCurrentView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ using TrailBlazr.Views;
|
||||
|
||||
namespace TrailBlazr.ViewModels;
|
||||
|
||||
public abstract class ViewModelBase<TViewModel, TView> : INotifyPropertyChanged
|
||||
public abstract class ViewModelBase<TViewModel, TView> : INotifyPropertyChanged, IDisposable
|
||||
where TViewModel : ViewModelBase<TViewModel, TView>
|
||||
where TView : ViewBase<TView, TViewModel>
|
||||
{
|
||||
private bool disposed = false;
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected TView? View
|
||||
@@ -42,4 +44,24 @@ public abstract class ViewModelBase<TViewModel, TView> : INotifyPropertyChanged
|
||||
public virtual ValueTask Initialize(CancellationToken cancellationToken) => ValueTask.CompletedTask;
|
||||
|
||||
public virtual ValueTask ParametersSet(TView view, CancellationToken cancellationToken) => ValueTask.CompletedTask;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
this.View = null;
|
||||
this.PropertyChanged = null;
|
||||
}
|
||||
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TrailBlazr.Components;
|
||||
using TrailBlazr.ViewModels;
|
||||
|
||||
namespace TrailBlazr.Views;
|
||||
public abstract class ViewBase<TView, TViewModel> : ComponentBase
|
||||
public abstract class ViewBase<TView, TViewModel> : ComponentBase, IDisposable
|
||||
where TView : ViewBase<TView, TViewModel>
|
||||
where TViewModel : ViewModelBase<TViewModel, TView>
|
||||
{
|
||||
public readonly static TimeSpan InitializationTimeout = TimeSpan.FromSeconds(5);
|
||||
private bool disposed = false;
|
||||
|
||||
[Inject]
|
||||
public TViewModel ViewModel { get; set; } = default!;
|
||||
public required TViewModel ViewModel { get; set; }
|
||||
[Inject]
|
||||
protected ILogger<TView> Logger { get; set; } = default!;
|
||||
public required ILogger<TView> Logger { get; set; }
|
||||
[CascadingParameter]
|
||||
public required ViewContainer ViewContainer { get; set; }
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
@@ -27,6 +31,11 @@ public abstract class ViewBase<TView, TViewModel> : ComponentBase
|
||||
throw new InvalidOperationException($"View is not of type {typeof(TView).Name}. Actual type: {this.GetType().Name}");
|
||||
}
|
||||
|
||||
if (this.ViewContainer is null)
|
||||
{
|
||||
throw new InvalidOperationException("ViewContainer is not set. Ensure that this view is placed within a ViewContainer component");
|
||||
}
|
||||
|
||||
this.ViewModel.SetView(view);
|
||||
using var initializationCts = new CancellationTokenSource(InitializationTimeout);
|
||||
_ = this.ViewModel ?? throw new InvalidOperationException("Cannot initialize ViewModel. ViewModel is null");
|
||||
@@ -61,5 +70,26 @@ public abstract class ViewBase<TView, TViewModel> : ComponentBase
|
||||
{
|
||||
await this.InvokeAsync(this.StateHasChanged);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!this.disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
this.ViewModel = null!;
|
||||
this.Logger = null!;
|
||||
this.ViewContainer = null!;
|
||||
}
|
||||
|
||||
this.disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user