Fixed disposer?

This commit is contained in:
TheXamlGuy
2024-01-28 19:31:09 +00:00
parent 6d40220412
commit 3917639e8d
10 changed files with 79 additions and 88 deletions
@@ -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}">
<UserControl.Resources>
<SolidColorBrush x:Key="ButtonBackground" Color="Transparent" />
<SolidColorBrush x:Key="ButtonBorderBrush" Color="Transparent" />
@@ -8,4 +8,6 @@ public sealed partial class MediaButtonView :
{
public MediaButtonView() =>
this.InitializeComponent(ref _contentLoaded);
private MediaButtonViewModel ViewModel => (MediaButtonViewModel)DataContext;
}
@@ -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<Changed<PlaybackInformation>>
{
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<PlaybackInformation> 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;
}
}
@@ -5,28 +5,31 @@ namespace Hyperbar.Widget.MediaController.Windows;
public class MediaControllerHandler(IMediator mediator,
IServiceScopeProvider<MediaController> scopeProvider,
ICache<MediaController, MediaControllerViewModel> cache) :
INotificationHandler<Created<MediaController>>
INotificationHandler<Created<MediaController>>,
INotificationHandler<Removed<MediaController>>
{
public async Task Handle(Created<MediaController> notification,
CancellationToken cancellationToken)
{
if (notification.Value is MediaController mediaController)
if (notification.Value is MediaController mediaController &&
scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope) &&
serviceScope?.ServiceProvider.GetService<IFactory<MediaController, MediaControllerViewModel?>>()
is IFactory<MediaController, MediaControllerViewModel?> factory &&
factory.Create(mediaController) is MediaControllerViewModel viewModel)
{
if (scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope))
cache.Add(mediaController, viewModel);
await mediator.PublishAsync(new Created<MediaControllerViewModel>(viewModel), cancellationToken);
}
}
if (serviceScope is not null)
{
if (serviceScope.ServiceProvider.GetService<IFactory<MediaController, MediaControllerViewModel?>>()
is IFactory<MediaController, MediaControllerViewModel?> factory)
{
if (factory.Create(mediaController) is MediaControllerViewModel mediaControllerViewModel)
{
cache.Add(mediaController, mediaControllerViewModel);
await mediator.PublishAsync(new Created<MediaControllerViewModel>(mediaControllerViewModel),
cancellationToken);
}
}
}
public async Task Handle(Removed<MediaController> notification, CancellationToken cancellationToken)
{
if (notification.Value is MediaController mediaController &&
cache.TryGetValue(mediaController, out MediaControllerViewModel? viewModel) &&
viewModel is not null)
{
await mediator.PublishAsync(new Removed<MediaControllerViewModel>(viewModel), cancellationToken);
cache.Remove(mediaController);
}
}
}
@@ -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<MediaController>(session.Value));
cache.Remove(session);
}
}
@@ -30,8 +30,6 @@ public class MediaControllerViewModel :
Add<MediaButtonViewModel>(PlaybackButtonType.Forward,
"Forward", "\uEB9D",
new RelayCommand(async () => await mediator.PublishAsync<Forward>()));
mediator.Subscribe(this);
}
public ITemplateFactory TemplateFactory { get; set; }
-10
View File
@@ -41,16 +41,6 @@ public class Cache<TKey, TValue>(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();
@@ -1,10 +1,3 @@
using System.Collections;
using System.Collections.Specialized;
namespace Hyperbar;
namespace Hyperbar;
public interface IObservableCollectionViewModel<TItem> :
IList<TItem>,
IList,
IReadOnlyList<TItem>,
INotifyCollectionChanged;
public interface IObservableCollectionViewModel<TItem>;
@@ -11,6 +11,10 @@ namespace Hyperbar;
public partial class ObservableCollectionViewModel<TItem> :
ObservableObject,
IObservableCollectionViewModel<TItem>,
IList<TItem>,
IList,
IReadOnlyList<TItem>,
INotifyCollectionChanged,
INotificationHandler<Removed<TItem>>,
INotificationHandler<Created<TItem>>,
INotificationHandler<Inserted<TItem>>,
@@ -134,6 +138,12 @@ public partial class ObservableCollectionViewModel<TItem> :
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<TItem> :
}
}
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<TItem> :
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<TItem> GetEnumerator() =>
collection.GetEnumerator();
@@ -187,15 +208,9 @@ public partial class ObservableCollectionViewModel<TItem> :
{
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<TItem> :
return false;
}
Disposer.Remove(this, item);
Disposer.Dispose(item);
RemoveItem(index);
return true;
@@ -302,14 +317,13 @@ public partial class ObservableCollectionViewModel<TItem> :
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);
+9 -11
View File
@@ -8,7 +8,7 @@ public class Mediator(IServiceProvider provider,
IDispatcher dispatcher) :
IMediator
{
private readonly ConcurrentDictionary<object, List<dynamic>> subjects = [];
private readonly ConcurrentDictionary<object, List<dynamic>> subscriptions = [];
public Task PublishAsync<TNotification>(object key,
CancellationToken cancellationToken = default)
@@ -46,11 +46,14 @@ public class Mediator(IServiceProvider provider,
List<INotificationHandler<TNotification>> handlers =
provider.GetServices<INotificationHandler<TNotification>>().ToList();
foreach (KeyValuePair<object, List<dynamic>> handler in subjects)
foreach (KeyValuePair<object, List<dynamic>> 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<object> { handler }, (value, collection) =>
subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", new List<object> { handler }, (value, collection) =>
{
collection.Add(handler);
return collection;