From 3917639e8d3e9b68bc38195887762cd9f1121b7b Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Sun, 28 Jan 2024 19:31:09 +0000 Subject: [PATCH] Fixed disposer? --- .../MediaButtonView.xaml | 3 +- .../MediaButtonView.xaml.cs | 2 + .../MediaButtonViewModel.cs | 32 +++++------- .../MediaControllerHandler.cs | 35 +++++++------ .../MediaControllerManager.cs | 2 +- .../MediaControllerViewModel.cs | 2 - Hyperbar/Lifecycles/Cache.cs | 10 ---- .../IObservableCollectionViewModel.cs | 11 +--- .../ObservableCollectionViewModel.cs | 50 ++++++++++++------- Hyperbar/Mediators/Mediator.cs | 20 ++++---- 10 files changed, 79 insertions(+), 88 deletions(-) diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml b/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml index 3bc7768..585ba8d 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml +++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml @@ -4,7 +4,8 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:interactions="using:Microsoft.Xaml.Interactions.Core" - xmlns:interactivity="using:Microsoft.Xaml.Interactivity"> + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + Visibility="{x:Bind ViewModel.Visible, Mode=OneWay}"> diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml.cs b/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml.cs index 8bbe98f..b35ceff 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonView.xaml.cs @@ -8,4 +8,6 @@ public sealed partial class MediaButtonView : { public MediaButtonView() => this.InitializeComponent(ref _contentLoaded); + + private MediaButtonViewModel ViewModel => (MediaButtonViewModel)DataContext; } diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs index 96210e4..4df17f8 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs @@ -2,27 +2,19 @@ namespace Hyperbar.Widget.MediaController.Windows; -public class MediaButtonViewModel : - WidgetButtonViewModel, +public class MediaButtonViewModel(IServiceFactory serviceFactory, + IMediator mediator, + IDisposer disposer, + ITemplateFactory templateFactory, + PlaybackButtonType buttonType, + Guid guid = default, + string? text = null, + string? icon = null, + RelayCommand? command = null) : + WidgetButtonViewModel(serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command), IInitialization, INotificationHandler> { - private readonly PlaybackButtonType buttonType; - - public MediaButtonViewModel(IServiceFactory serviceFactory, - IMediator mediator, - IDisposer disposer, - ITemplateFactory templateFactory, - PlaybackButtonType buttonType, - Guid guid = default, - string? text = null, - string? icon = null, - RelayCommand? command = null) : base (serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command) - { - this.buttonType = buttonType; - mediator.Subscribe(this); - } - public Task Handle(Changed notification, CancellationToken cancellationToken) { @@ -31,10 +23,10 @@ public class MediaButtonViewModel : switch (buttonType) { case PlaybackButtonType.Play: - Visible = information.Status is PlaybackStatus.Playing; + Visible = information.Status is PlaybackStatus.Paused; break; case PlaybackButtonType.Pause: - Visible = information.Status is PlaybackStatus.Paused; + Visible = information.Status is PlaybackStatus.Playing; break; } } diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs index 59b0072..0a2d16d 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs @@ -5,28 +5,31 @@ namespace Hyperbar.Widget.MediaController.Windows; public class MediaControllerHandler(IMediator mediator, IServiceScopeProvider scopeProvider, ICache cache) : - INotificationHandler> + INotificationHandler>, + INotificationHandler> { public async Task Handle(Created notification, CancellationToken cancellationToken) { - if (notification.Value is MediaController mediaController) + if (notification.Value is MediaController mediaController && + scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope) && + serviceScope?.ServiceProvider.GetService>() + is IFactory factory && + factory.Create(mediaController) is MediaControllerViewModel viewModel) { - if (scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope)) + cache.Add(mediaController, viewModel); + await mediator.PublishAsync(new Created(viewModel), cancellationToken); + } + } - if (serviceScope is not null) - { - if (serviceScope.ServiceProvider.GetService>() - is IFactory factory) - { - if (factory.Create(mediaController) is MediaControllerViewModel mediaControllerViewModel) - { - cache.Add(mediaController, mediaControllerViewModel); - await mediator.PublishAsync(new Created(mediaControllerViewModel), - cancellationToken); - } - } - } + public async Task Handle(Removed notification, CancellationToken cancellationToken) + { + if (notification.Value is MediaController mediaController && + cache.TryGetValue(mediaController, out MediaControllerViewModel? viewModel) && + viewModel is not null) + { + await mediator.PublishAsync(new Removed(viewModel), cancellationToken); + cache.Remove(mediaController); } } } \ No newline at end of file diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs index deb6923..9ab9815 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerManager.cs @@ -48,7 +48,7 @@ public class MediaControllerManager(IMediator mediator, { if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId)) { - await dispatcher.InvokeAsync(() => disposer.Dispose(session.Value)); + await mediator.PublishAsync(new Removed(session.Value)); cache.Remove(session); } } diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs index c5b8c3c..ef7638a 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs @@ -30,8 +30,6 @@ public class MediaControllerViewModel : Add(PlaybackButtonType.Forward, "Forward", "\uEB9D", new RelayCommand(async () => await mediator.PublishAsync())); - - mediator.Subscribe(this); } public ITemplateFactory TemplateFactory { get; set; } diff --git a/Hyperbar/Lifecycles/Cache.cs b/Hyperbar/Lifecycles/Cache.cs index c1bbf9b..2ef2866 100644 --- a/Hyperbar/Lifecycles/Cache.cs +++ b/Hyperbar/Lifecycles/Cache.cs @@ -41,16 +41,6 @@ public class Cache(IDisposer disposer) : TValue value) { cache.TryAdd(key, value); - - disposer.Add(value, Disposable.Create(() => - { - Remove(key); - })); - - disposer.Add(key, Disposable.Create(() => - { - Remove(key); - })); } public void Clear() => cache.Clear(); diff --git a/Hyperbar/Lifecycles/IObservableCollectionViewModel.cs b/Hyperbar/Lifecycles/IObservableCollectionViewModel.cs index 2e1df9c..18093d0 100644 --- a/Hyperbar/Lifecycles/IObservableCollectionViewModel.cs +++ b/Hyperbar/Lifecycles/IObservableCollectionViewModel.cs @@ -1,10 +1,3 @@ -using System.Collections; -using System.Collections.Specialized; +namespace Hyperbar; -namespace Hyperbar; - -public interface IObservableCollectionViewModel : - IList, - IList, - IReadOnlyList, - INotifyCollectionChanged; \ No newline at end of file +public interface IObservableCollectionViewModel; \ No newline at end of file diff --git a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs index 3a70763..b43e34c 100644 --- a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs +++ b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs @@ -11,6 +11,10 @@ namespace Hyperbar; public partial class ObservableCollectionViewModel : ObservableObject, IObservableCollectionViewModel, + IList, + IList, + IReadOnlyList, + INotifyCollectionChanged, INotificationHandler>, INotificationHandler>, INotificationHandler>, @@ -134,6 +138,12 @@ public partial class ObservableCollectionViewModel : InsertItem(index, item); } + public void Add(object item) + { + int index = collection.Count; + InsertItem(index, (TItem)item); + } + int IList.Add(object? value) { TItem? item = default; @@ -159,7 +169,15 @@ public partial class ObservableCollectionViewModel : } } - public void Clear() => ClearItems(); + public void Clear() + { + foreach (TItem item in collection) + { + Disposer.Dispose(item); + } + + ClearItems(); + } public bool Contains(TItem item) => collection.Contains(item); @@ -173,8 +191,11 @@ public partial class ObservableCollectionViewModel : void ICollection.CopyTo(Array array, int index) => collection.CopyTo((TItem[])array, index); - public void Dispose() => + public virtual void Dispose() + { + GC.SuppressFinalize(this); Disposer.Dispose(this); + } public System.Collections.Generic.IEnumerator GetEnumerator() => collection.GetEnumerator(); @@ -187,15 +208,9 @@ public partial class ObservableCollectionViewModel : { foreach (TItem item in this.ToList()) { - if (notification.Value is not null) + if (notification.Value is not null && notification.Value.Equals(item)) { - if (notification.Value.Equals(item)) - { - if (item is IDisposable disposable) - { - disposable.Dispose(); - } - } + Remove(item); } } @@ -279,7 +294,7 @@ public partial class ObservableCollectionViewModel : return false; } - Disposer.Remove(this, item); + Disposer.Dispose(item); RemoveItem(index); return true; @@ -302,14 +317,13 @@ public partial class ObservableCollectionViewModel : protected virtual void InsertItem(int index, TItem value) { - Disposer.Add(this, Disposable.Create(() => + Disposer.Add(this, value); + Disposer.Add(value, value, Disposable.Create(() => { - Remove(value); - })); - - Disposer.Add(value, Disposable.Create(() => - { - Remove(value); + if (value is IList collection) + { + collection.Clear(); + } })); collection.Insert(index, value); diff --git a/Hyperbar/Mediators/Mediator.cs b/Hyperbar/Mediators/Mediator.cs index 955ba63..285be2c 100644 --- a/Hyperbar/Mediators/Mediator.cs +++ b/Hyperbar/Mediators/Mediator.cs @@ -8,7 +8,7 @@ public class Mediator(IServiceProvider provider, IDispatcher dispatcher) : IMediator { - private readonly ConcurrentDictionary> subjects = []; + private readonly ConcurrentDictionary> subscriptions = []; public Task PublishAsync(object key, CancellationToken cancellationToken = default) @@ -46,11 +46,14 @@ public class Mediator(IServiceProvider provider, List> handlers = provider.GetServices>().ToList(); - foreach (KeyValuePair> handler in subjects) + foreach (KeyValuePair> subscriber in subscriptions) { - if (key is not null && handler.Key.Equals(key) || handler.Key.Equals(typeof(TNotification))) + if (subscriber.Key.Equals($"{(key is not null ? $"{key}:" : "")}{typeof(TNotification)}")) { - handlers.Add(handler.Value[0]); + foreach (dynamic handler in subscriber.Value) + { + handlers.Add(handler); + } } } @@ -111,14 +114,9 @@ public class Mediator(IServiceProvider provider, foreach (Type interfaceType in GetNotificationHandlerInterfaces(handlerType)) { - if (interfaceType.GetGenericArguments().FirstOrDefault() - is Type argumentType) + if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) { - if (object.Equals(key, default)) - { - - } - subjects.AddOrUpdate(key ?? argumentType, new List { handler }, (value, collection) => + subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", new List { handler }, (value, collection) => { collection.Add(handler); return collection;