diff --git a/Hyperbar.UI.Windows/NavigateAction.cs b/Hyperbar.UI.Windows/NavigateAction.cs index eb7160b..78e839e 100644 --- a/Hyperbar.UI.Windows/NavigateAction.cs +++ b/Hyperbar.UI.Windows/NavigateAction.cs @@ -24,7 +24,7 @@ public sealed class NavigateAction : { if (frameworkElement.DataContext is IObservableViewModel observableViewModel) { - observableViewModel.Mediator.PublishAsync(new Navigate(Path)) + observableViewModel.Publisher.PublishAsync(new Navigate(Path)) .GetAwaiter().GetResult(); } } diff --git a/Hyperbar.UI.Windows/ViewModelTemplate.cs b/Hyperbar.UI.Windows/ViewModelTemplate.cs index 01fe947..d63e962 100644 --- a/Hyperbar.UI.Windows/ViewModelTemplate.cs +++ b/Hyperbar.UI.Windows/ViewModelTemplate.cs @@ -4,6 +4,15 @@ using Microsoft.UI.Xaml.Markup; namespace Hyperbar.UI.Windows; +public class ViewModelBinder +{ + public void Bind(object viewModel, + FrameworkElement view) + { + view.DataContext ??= viewModel; + + } +} public class ViewModelTemplate(IViewModelTemplateDescriptorProvider descriptors) : DataTemplateSelector, IViewModelTemplate @@ -19,7 +28,7 @@ public class ViewModelTemplate(IViewModelTemplateDescriptorProvider descriptors) DependencyObject container) => SelectTemplateCore(item); - private DataTemplate CreateDataTemplate(IViewModelTemplateDescriptor descriptor) + private static DataTemplate CreateDataTemplate(IViewModelTemplateDescriptor descriptor) { string xamlString = @$" diff --git a/Hyperbar.UI.Windows/WindowHandler.cs b/Hyperbar.UI.Windows/WindowHandler.cs index 31bad69..c408583 100644 --- a/Hyperbar.UI.Windows/WindowHandler.cs +++ b/Hyperbar.UI.Windows/WindowHandler.cs @@ -20,7 +20,7 @@ public class WindowHandler : public Task Handle(Navigate args, CancellationToken cancellationToken) { - if (args.Template is Window window) + if (args.View is Window window) { if (window.Content is FrameworkElement content) { @@ -33,8 +33,8 @@ public class WindowHandler : } } + //ViewModelBinder.Bind(args.ViewModel, content); window.Closed += HandleClosed; - content.DataContext = args.Content; } window.Activate(); diff --git a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs index 160945f..301b7a9 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaButtonViewModel.cs @@ -5,10 +5,11 @@ namespace Hyperbar.Widget.MediaController.Windows; public partial class MediaButtonViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, IRelayCommand invokeCommand) : - WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer), + WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), INotificationHandler>>, IMediaButtonViewModel { @@ -29,5 +30,5 @@ public partial class MediaButtonViewModel(IServiceProvider service } public override async Task InitializeAsync() => - await Mediator.PublishAsync>(); + await Publisher.PublishAsync>(); } \ No newline at end of file diff --git a/Hyperbar.Widget.MediaController.Windows/MediaController.cs b/Hyperbar.Widget.MediaController.Windows/MediaController.cs index 99b4b15..40d4f5c 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaController.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaController.cs @@ -14,23 +14,24 @@ public class MediaController : IDisposable { private readonly IDisposer disposer; - private readonly IMediator mediator; + private readonly IPublisher publisher; private readonly GlobalSystemMediaTransportControlsSession session; private bool isNextEnabled; private bool isPreviousEnabled; private GlobalSystemMediaTransportControlsSessionPlaybackStatus playbackStatus; - public MediaController(IMediator mediator, + public MediaController(IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, GlobalSystemMediaTransportControlsSession session) { - this.mediator = mediator; + this.publisher = publisher; this.disposer = disposer; this.session = session; disposer.Add(this); - mediator.Subscribe(this); + subscriber.Add(this); session.MediaPropertiesChanged += OnMediaPropertiesChanged; session.PlaybackInfoChanged += OnPlaybackInfoChanged; @@ -117,7 +118,7 @@ public class MediaController : buffer = memoryStream.ToArray(); } - await mediator.PublishAsync(new Changed(new MediaInformation(mediaProperties.Title, + await publisher.PublishAsync(new Changed(new MediaInformation(mediaProperties.Title, mediaProperties.Artist, buffer))); } catch @@ -133,7 +134,7 @@ public class MediaController : GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo = session.GetPlaybackInfo(); - await mediator.PublishAsync(new Changed>(new + await publisher.PublishAsync(new Changed>(new MediaButton(playbackInfo.PlaybackStatus is GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing ? new MediaButtonPlaying() : @@ -142,7 +143,7 @@ public class MediaController : bool isPreviousEnabled = playbackInfo.Controls.IsPreviousEnabled; if (this.isPreviousEnabled != isPreviousEnabled) { - await mediator.PublishAsync(new Changed>(new + await publisher.PublishAsync(new Changed>(new MediaButton(isPreviousEnabled ? new MediaButtonEnabled() : new MediaButtonDisabled()))); @@ -152,7 +153,7 @@ public class MediaController : bool isNextEnabled = playbackInfo.Controls.IsNextEnabled; if (this.isNextEnabled != isNextEnabled) { - await mediator.PublishAsync(new Changed>(new + await publisher.PublishAsync(new Changed>(new MediaButton(isNextEnabled ? new MediaButtonEnabled() : new MediaButtonDisabled()))); diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs index 7faf3bc..1cd6f2d 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerHandler.cs @@ -2,7 +2,7 @@ namespace Hyperbar.Widget.MediaController.Windows; -public class MediaControllerHandler(IMediator mediator, +public class MediaControllerHandler(IPublisher publisher, IServiceScopeProvider scopeProvider, ICache cache) : INotificationHandler>, @@ -18,7 +18,7 @@ public class MediaControllerHandler(IMediator mediator, factory.Create(mediaController) is MediaControllerViewModel viewModel) { cache.Add(mediaController, viewModel); - await mediator.PublishAsync(new Create(viewModel), cancellationToken); + await publisher.PublishAsync(new Create(viewModel), cancellationToken); } } @@ -28,7 +28,7 @@ public class MediaControllerHandler(IMediator mediator, cache.TryGetValue(mediaController, out MediaControllerViewModel? viewModel) && viewModel is not null) { - await mediator.PublishAsync(new Remove(viewModel), cancellationToken); + await publisher.PublishAsync(new Remove(viewModel), cancellationToken); cache.Remove(mediaController); } } diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerService.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerService.cs index 8dfdb34..122daf2 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerService.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerService.cs @@ -3,7 +3,7 @@ using Windows.Media.Control; namespace Hyperbar.Widget.MediaController.Windows; -public class MediaControllerService(IMediator mediator, +public class MediaControllerService(IPublisher publisher, IFactory factory) : IHostedService { @@ -34,7 +34,7 @@ public class MediaControllerService(IMediator mediator, { if (factory.Create(session) is MediaController mediaController) { - await mediator.PublishAsync(new Create(mediaController)); + await publisher.PublishAsync(new Create(mediaController)); cache.Add(new KeyValuePair(session, mediaController)); } @@ -53,7 +53,7 @@ public class MediaControllerService(IMediator mediator, { if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId)) { - await mediator.PublishAsync(new Remove(session.Value)); + await publisher.PublishAsync(new Remove(session.Value)); cache.Remove(session); } } diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs index 877b618..4e9c346 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerViewModel.cs @@ -10,21 +10,22 @@ public class MediaControllerViewModel : public MediaControllerViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, - IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer) { Template = template; Add(); Add>(new RelayCommand(async () => - await mediator.PublishAsync>())); + await publisher.PublishAsync>())); Add>(new RelayCommand(async () => - await mediator.PublishAsync>())); + await publisher.PublishAsync>())); Add>(new RelayCommand(async () => - await mediator.PublishAsync>())); + await publisher.PublishAsync>())); } public IViewModelTemplate Template { get; } diff --git a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs index 98ddf09..5962b4d 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaControllerWidgetViewModel.cs @@ -5,10 +5,11 @@ namespace Hyperbar.Widget.MediaController.Windows; public class MediaControllerWidgetViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, IEnumerable items) : - ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer, items), + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, items), IWidgetViewModel { public IViewModelTemplate Template => template; diff --git a/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs b/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs index 8222829..7d32c6e 100644 --- a/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs +++ b/Hyperbar.Widget.MediaController.Windows/MediaInformationViewModel.cs @@ -4,9 +4,10 @@ namespace Hyperbar.Widget.MediaController.Windows; public partial class MediaInformationViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer) : - WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer), + WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), INotificationHandler> { [ObservableProperty] @@ -32,5 +33,5 @@ public partial class MediaInformationViewModel(IServiceProvider serviceProvider, } public override async Task InitializeAsync() => - await Mediator.PublishAsync>(); + await Publisher.PublishAsync>(); } diff --git a/Hyperbar.Widget.Primary.Windows/PrimaryWidgetConfigurationHandler.cs b/Hyperbar.Widget.Primary.Windows/PrimaryWidgetConfigurationHandler.cs index b2ee4af..cb80ab2 100644 --- a/Hyperbar.Widget.Primary.Windows/PrimaryWidgetConfigurationHandler.cs +++ b/Hyperbar.Widget.Primary.Windows/PrimaryWidgetConfigurationHandler.cs @@ -1,8 +1,6 @@ -using Hyperbar.Widget; +namespace Hyperbar.Widget.Primary.Windows; -namespace Hyperbar.Widget.Primary.Windows; - -public class PrimaryWidgetConfigurationHandler(IMediator mediator, +public class PrimaryWidgetConfigurationHandler(IPublisher publisher, PrimaryWidgetConfiguration configuration, IFactory factory, IProvider provider, @@ -44,7 +42,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator, if (moved.Value is PrimaryCommandConfiguration configuration && provider.Get(configuration) is IWidgetComponentViewModel viewModel) { - await mediator.PublishAsync(new Move(configuration.Order, viewModel), + await publisher.PublishAsync(new Move(configuration.Order, viewModel), moved.Key.ParentId == Guid.Empty ? nameof(PrimaryWidgetViewModel) : moved.Key.ParentId, cancellationToken); @@ -61,8 +59,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator, if (added.Value is PrimaryCommandConfiguration configuration && factory.Create(configuration) is IWidgetComponentViewModel viewModel) { - await mediator.PublishAsync( - new Insert(configuration.Order, viewModel), + await publisher.PublishAsync(new Insert(configuration.Order, viewModel), added.Key.ParentId == Guid.Empty ? nameof(PrimaryWidgetViewModel) : added.Key.ParentId, cancellationToken); @@ -78,8 +75,7 @@ public class PrimaryWidgetConfigurationHandler(IMediator mediator, if (removed.Value is PrimaryCommandConfiguration configuration && provider.Get(configuration) is IWidgetComponentViewModel viewModel) { - await mediator.PublishAsync( - new Remove(viewModel), + await publisher.PublishAsync(new Remove(viewModel), removed.Key.ParentId == Guid.Empty ? nameof(PrimaryWidgetViewModel) : removed.Key.ParentId, cancellationToken); diff --git a/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs b/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs index 6cc2ca1..38cf022 100644 --- a/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs +++ b/Hyperbar.Widget.Primary.Windows/PrimaryWidgetViewModel.cs @@ -5,7 +5,8 @@ namespace Hyperbar.Widget.Primary.Windows; [NotificationHandler(nameof(PrimaryWidgetViewModel))] public class PrimaryWidgetViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer) : - ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer), + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), IWidgetViewModel; \ No newline at end of file diff --git a/Hyperbar.Widget.Primary.Windows/WidgetComponentViewModelEnumerator.cs b/Hyperbar.Widget.Primary.Windows/WidgetComponentViewModelEnumerator.cs index e4ba679..1dbbf11 100644 --- a/Hyperbar.Widget.Primary.Windows/WidgetComponentViewModelEnumerator.cs +++ b/Hyperbar.Widget.Primary.Windows/WidgetComponentViewModelEnumerator.cs @@ -1,14 +1,13 @@ -using Hyperbar.Widget; - -namespace Hyperbar.Widget.Primary.Windows; +namespace Hyperbar.Widget.Primary.Windows; public class WidgetComponentViewModelEnumerator(PrimaryWidgetConfiguration configuration, - IMediator mediator, + IPublisher publisher, IFactory factory, ICache<(Guid ParentId, Guid Id), PrimaryCommandConfiguration> cache) : INotificationHandler> { - public async Task Handle(Enumerate notification, CancellationToken cancellationToken) + public async Task Handle(Enumerate notification, + CancellationToken cancellationToken) { Stack<(Guid, List)> stack = new(); stack.Push((Guid.Empty, configuration.Commands)); @@ -30,7 +29,7 @@ public class WidgetComponentViewModelEnumerator(PrimaryWidgetConfiguration confi { if (factory.Create(item) is IWidgetComponentViewModel viewModel) { - await mediator.PublishAsync(new Create(viewModel), nameof(PrimaryWidgetViewModel), + await publisher.PublishAsync(new Create(viewModel), nameof(PrimaryWidgetViewModel), cancellationToken); } } diff --git a/Hyperbar.Widget/WidgetButtonViewModel.cs b/Hyperbar.Widget/WidgetButtonViewModel.cs index 3f93d15..7e520fa 100644 --- a/Hyperbar.Widget/WidgetButtonViewModel.cs +++ b/Hyperbar.Widget/WidgetButtonViewModel.cs @@ -6,12 +6,13 @@ namespace Hyperbar.Widget; [NotificationHandler(nameof(Id))] public partial class WidgetButtonViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, Guid id, string? text = null, string? icon = null, - RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer) + RelayCommand? invokeCommand = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer) { [ObservableProperty] private string? icon = icon; diff --git a/Hyperbar.Widget/WidgetComponentViewModel.cs b/Hyperbar.Widget/WidgetComponentViewModel.cs index 7ef11e8..cac5048 100644 --- a/Hyperbar.Widget/WidgetComponentViewModel.cs +++ b/Hyperbar.Widget/WidgetComponentViewModel.cs @@ -6,17 +6,19 @@ public partial class WidgetComponentViewModel : { public WidgetComponentViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, - IEnumerable items) : base(serviceProvider, serviceFactory, mediator, disposer, items) + IEnumerable items) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer, items) { } public WidgetComponentViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, - IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer) { } diff --git a/Hyperbar.Widget/WidgetExtensionEnumerator.cs b/Hyperbar.Widget/WidgetExtensionEnumerator.cs index cdf72e3..49be899 100644 --- a/Hyperbar.Widget/WidgetExtensionEnumerator.cs +++ b/Hyperbar.Widget/WidgetExtensionEnumerator.cs @@ -6,7 +6,7 @@ namespace Hyperbar.Widget; public class WidgetExtensionEnumerator(IFactory factory, IHostEnvironment hostEnvironment, - IMediator mediator) : + IPublisher publisher) : INotificationHandler> { public Task Handle(Enumerate args, @@ -29,7 +29,7 @@ public class WidgetExtensionEnumerator(IFactory factory, { if (factory.Create(widgetType) is IWidget widget) { - await mediator.PublishAsync(new Create(new WidgetExtension(widget, + await publisher.PublishAsync(new Create(new WidgetExtension(widget, new WidgetAssembly(assembly))), cancellationToken); } } diff --git a/Hyperbar.Widget/WidgetExtensionHandler.cs b/Hyperbar.Widget/WidgetExtensionHandler.cs index 5b53aee..ddccdeb 100644 --- a/Hyperbar.Widget/WidgetExtensionHandler.cs +++ b/Hyperbar.Widget/WidgetExtensionHandler.cs @@ -3,7 +3,7 @@ namespace Hyperbar.Widget; public class WidgetExtensionHandler(IServiceProvider provider, - IMediator mediator, + IPublisher publisher, IProxyServiceCollection typedServices) : INotificationHandler> { @@ -22,7 +22,7 @@ public class WidgetExtensionHandler(IServiceProvider provider, }); IWidgetHost host = builder.Build(); - await mediator.PublishAsync(new Create(host), + await publisher.PublishAsync(new Create(host), cancellationToken); } } diff --git a/Hyperbar.Widget/WidgetExtensionInitializer.cs b/Hyperbar.Widget/WidgetExtensionInitializer.cs index 87954d5..58b95cb 100644 --- a/Hyperbar.Widget/WidgetExtensionInitializer.cs +++ b/Hyperbar.Widget/WidgetExtensionInitializer.cs @@ -1,8 +1,8 @@ namespace Hyperbar.Widget; -public class WidgetExtensionInitializer(IMediator mediator) : +public class WidgetExtensionInitializer(IPublisher publisher) : IInitializer { public async Task InitializeAsync() => - await mediator.PublishAsync>(); + await publisher.PublishAsync>(); } \ No newline at end of file diff --git a/Hyperbar.Widget/WidgetHost.cs b/Hyperbar.Widget/WidgetHost.cs index ad476d2..f06b8b0 100644 --- a/Hyperbar.Widget/WidgetHost.cs +++ b/Hyperbar.Widget/WidgetHost.cs @@ -7,17 +7,17 @@ public sealed class WidgetHost : IWidgetHost { private readonly IServiceProvider services; - private readonly IMediator mediator; + private readonly IPublisher publisher; private readonly IProxyService proxyMediator; private readonly IEnumerable hostedServices; public WidgetHost(IServiceProvider services, - IMediator mediator, + IPublisher publisher, IProxyService proxyMediator, IEnumerable hostedServices) { this.services = services; - this.mediator = mediator; + this.publisher = publisher; this.proxyMediator = proxyMediator; this.hostedServices = hostedServices; } @@ -41,11 +41,11 @@ public sealed class WidgetHost : if (proxyMediator.Proxy is IMediator mediator) { - await mediator.PublishAsync(new Started(this), + await publisher.PublishAsync(new Started(this), cancellationToken); } - await this.mediator.PublishAsync(new Started(this), + await this.publisher.PublishAsync(new Started(this), cancellationToken); } diff --git a/Hyperbar.Widget/WidgetMenuViewModel.cs b/Hyperbar.Widget/WidgetMenuViewModel.cs index bd893bc..71edc7f 100644 --- a/Hyperbar.Widget/WidgetMenuViewModel.cs +++ b/Hyperbar.Widget/WidgetMenuViewModel.cs @@ -6,12 +6,13 @@ namespace Hyperbar.Widget; [NotificationHandler(nameof(Id))] public partial class WidgetMenuViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, Guid id = default, string? text = null, string? icon = null, - RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer) + RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer) { [ObservableProperty] private IRelayCommand? click = command; diff --git a/Hyperbar.Widget/WidgetSplitButtonViewModel.cs b/Hyperbar.Widget/WidgetSplitButtonViewModel.cs index 4213d4e..d848d70 100644 --- a/Hyperbar.Widget/WidgetSplitButtonViewModel.cs +++ b/Hyperbar.Widget/WidgetSplitButtonViewModel.cs @@ -6,13 +6,14 @@ namespace Hyperbar.Widget; [NotificationHandler(nameof(Id))] public partial class WidgetSplitButtonViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, IEnumerable items, Guid id = default, string? text = null, string? icon = null, - RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, mediator, disposer, items) + RelayCommand? command = null) : WidgetComponentViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, items) { [ObservableProperty] private IRelayCommand? click = command; diff --git a/Hyperbar.Widget/WidgetStartedHandler.cs b/Hyperbar.Widget/WidgetStartedHandler.cs index 5b08a5f..0869956 100644 --- a/Hyperbar.Widget/WidgetStartedHandler.cs +++ b/Hyperbar.Widget/WidgetStartedHandler.cs @@ -2,7 +2,7 @@ namespace Hyperbar.Widget; -public class WidgetStartedHandler(IMediator mediator) : +public class WidgetStartedHandler(IPublisher publisher) : INotificationHandler> { public async Task Handle(Started notification, @@ -12,7 +12,7 @@ public class WidgetStartedHandler(IMediator mediator) : { if (host.Services.GetService() is IWidgetViewModel viewModel) { - await mediator.PublishAsync(new Create(viewModel), + await publisher.PublishAsync(new Create(viewModel), nameof(IWidgetHostViewModel), cancellationToken); } } diff --git a/Hyperbar.Widget/WidgetViewModelEnumerator.cs b/Hyperbar.Widget/WidgetViewModelEnumerator.cs index d35bca8..199035a 100644 --- a/Hyperbar.Widget/WidgetViewModelEnumerator.cs +++ b/Hyperbar.Widget/WidgetViewModelEnumerator.cs @@ -3,7 +3,7 @@ namespace Hyperbar.Widget; public class WidgetViewModelEnumerator(IWidgetHost host, - IMediator mediator) : + IPublisher publisher) : INotificationHandler> { public async Task Handle(Enumerate notification, @@ -13,7 +13,7 @@ public class WidgetViewModelEnumerator(IWidgetHost host, { foreach (IWidgetViewModel viewModel in viewModels) { - await mediator.PublishAsync(new Create(viewModel), + await publisher.PublishAsync(new Create(viewModel), nameof(IWidgetHostViewModel), cancellationToken); } } diff --git a/Hyperbar.Windows/App.xaml b/Hyperbar.Windows/App.xaml index eda95de..2ec19df 100644 --- a/Hyperbar.Windows/App.xaml +++ b/Hyperbar.Windows/App.xaml @@ -2,16 +2,12 @@ + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - - - \ No newline at end of file diff --git a/Hyperbar.Windows/ApplicationBarViewModel.cs b/Hyperbar.Windows/ApplicationBarViewModel.cs index 77bd9a6..da12701 100644 --- a/Hyperbar.Windows/ApplicationBarViewModel.cs +++ b/Hyperbar.Windows/ApplicationBarViewModel.cs @@ -10,8 +10,9 @@ public partial class ApplicationBarViewModel : public ApplicationBarViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, - IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer) { Template = template; diff --git a/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs b/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs index a345f95..aa809d1 100644 --- a/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs +++ b/Hyperbar.Windows/GeneralSettingsNavigationViewModel.cs @@ -2,9 +2,10 @@ public class GeneralSettingsNavigationViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, string text) : - NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text) + NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text) { } \ No newline at end of file diff --git a/Hyperbar.Windows/PrimaryViewModel.cs b/Hyperbar.Windows/PrimaryViewModel.cs index 6915cbc..9c19576 100644 --- a/Hyperbar.Windows/PrimaryViewModel.cs +++ b/Hyperbar.Windows/PrimaryViewModel.cs @@ -7,10 +7,11 @@ namespace Hyperbar.Widget; public partial class PrimaryViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, int index) : - ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer), + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), IWidgetHostViewModel { [ObservableProperty] diff --git a/Hyperbar.Windows/SecondaryViewModel.cs b/Hyperbar.Windows/SecondaryViewModel.cs index e9190e3..2cd0874 100644 --- a/Hyperbar.Windows/SecondaryViewModel.cs +++ b/Hyperbar.Windows/SecondaryViewModel.cs @@ -13,9 +13,10 @@ public partial class SecondaryViewModel : public SecondaryViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, - int index) : base(serviceProvider, serviceFactory, mediator, disposer) + int index) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer) { Template = template; this.index = index; diff --git a/Hyperbar.Windows/SettingsButtonViewModel.cs b/Hyperbar.Windows/SettingsButtonViewModel.cs index 2079251..d7aaf3c 100644 --- a/Hyperbar.Windows/SettingsButtonViewModel.cs +++ b/Hyperbar.Windows/SettingsButtonViewModel.cs @@ -5,9 +5,9 @@ namespace Hyperbar.Windows; public partial class SettingsButtonViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, IDisposer disposer) : - ObservableViewModel(serviceProvider, serviceFactory, mediator, disposer) + ObservableViewModel(serviceProvider, serviceFactory, publisher, disposer) { public IViewModelTemplate Template => template; } \ No newline at end of file diff --git a/Hyperbar.Windows/SettingsViewModel.cs b/Hyperbar.Windows/SettingsViewModel.cs index 0a5111d..c5781f4 100644 --- a/Hyperbar.Windows/SettingsViewModel.cs +++ b/Hyperbar.Windows/SettingsViewModel.cs @@ -7,9 +7,10 @@ public partial class SettingsViewModel : { public SettingsViewModel(IViewModelTemplate template, IServiceProvider serviceProvider, - IServiceFactory serviceFactory, - IMediator mediator, - IDisposer disposer) : base(serviceProvider, serviceFactory, mediator, disposer) + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer) { Template = template; diff --git a/Hyperbar.Windows/WidgetNavigationViewModel.cs b/Hyperbar.Windows/WidgetNavigationViewModel.cs index 863ecbe..41708c1 100644 --- a/Hyperbar.Windows/WidgetNavigationViewModel.cs +++ b/Hyperbar.Windows/WidgetNavigationViewModel.cs @@ -2,9 +2,10 @@ public class WidgetNavigationViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, string text) : - NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text) + NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text) { } diff --git a/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs b/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs index 5e7a297..5903da8 100644 --- a/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs +++ b/Hyperbar.Windows/WidgetSettingsNavigationViewModel.cs @@ -2,10 +2,11 @@ public class WidgetSettingsNavigationViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, string text) : - NavigationViewModel(serviceProvider, serviceFactory, mediator, disposer, text) + NavigationViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer, text) { } diff --git a/Hyperbar/Configuration/ConfigurationInitializer.cs b/Hyperbar/Configuration/ConfigurationInitializer.cs index 58d368a..73ebc1c 100644 --- a/Hyperbar/Configuration/ConfigurationInitializer.cs +++ b/Hyperbar/Configuration/ConfigurationInitializer.cs @@ -1,6 +1,6 @@ namespace Hyperbar; -public class ConfigurationInitializer(IMediator mediator, +public class ConfigurationInitializer(IPublisher publisher, IConfigurationMonitor monitor, IConfigurationReader reader, IConfigurationWriter writer, @@ -21,7 +21,7 @@ public class ConfigurationInitializer(IMediator mediator, } } - await mediator.PublishAsync(new Changed(configuration)); + await publisher.PublishAsync(new Changed(configuration)); await monitor.InitializeAsync(); } } diff --git a/Hyperbar/Configuration/ConfigurationMonitor.cs b/Hyperbar/Configuration/ConfigurationMonitor.cs index bff11ca..1b20445 100644 --- a/Hyperbar/Configuration/ConfigurationMonitor.cs +++ b/Hyperbar/Configuration/ConfigurationMonitor.cs @@ -2,7 +2,7 @@ public class ConfigurationMonitor(IConfigurationFile configurationFile, IConfigurationReader reader, - IMediator mediator) : + IPublisher publisher) : IConfigurationMonitor where TConfiguration : class @@ -16,7 +16,7 @@ public class ConfigurationMonitor(IConfigurationFile(configuration)); + await publisher.PublishAsync(new Changed(configuration)); } } diff --git a/Hyperbar/Configuration/ConfigurationValueChangedNotification.cs b/Hyperbar/Configuration/ConfigurationValueChangedNotification.cs index fa351e3..e76e724 100644 --- a/Hyperbar/Configuration/ConfigurationValueChangedNotification.cs +++ b/Hyperbar/Configuration/ConfigurationValueChangedNotification.cs @@ -1,6 +1,6 @@ namespace Hyperbar; -public class ConfigurationValueChangedNotification(IMediator mediator, +public class ConfigurationValueChangedNotification(IPublisher publisher, Func> factory) : IConfigurationValueChangedNotification where TConfiguration : @@ -18,7 +18,7 @@ public class ConfigurationValueChangedNotification(IMedi if (value is null || !value.Equals(newValue)) { value = newValue; - await mediator.PublishAsync(new Changed(value)); + await publisher.PublishAsync(new Changed(value)); } } } diff --git a/Hyperbar/Extensions/IServiceCollectionExtensions.cs b/Hyperbar/Extensions/IServiceCollectionExtensions.cs index df71c07..efe3901 100644 --- a/Hyperbar/Extensions/IServiceCollectionExtensions.cs +++ b/Hyperbar/Extensions/IServiceCollectionExtensions.cs @@ -19,7 +19,7 @@ public static class IServiceCollectionExtensions class, new() { services.AddSingleton>(provider => - new ConfigurationValueChangedNotification(provider.GetRequiredService(), + new ConfigurationValueChangedNotification(provider.GetRequiredService(), factory)); return services; @@ -237,18 +237,6 @@ public static class IServiceCollectionExtensions return services; } - - public static IServiceCollection AddNotificationRelay(this IServiceCollection services) - where TFromNotification : - INotification - where TToNotification : - INotification, new() - { - return services.AddHandler>(); - } - public static IServiceCollection AddRange(this IServiceCollection services, IServiceCollection fromServices) { diff --git a/Hyperbar/Lifecycles/AsyncLock.cs b/Hyperbar/Lifecycles/AsyncLock.cs new file mode 100644 index 0000000..73b4450 --- /dev/null +++ b/Hyperbar/Lifecycles/AsyncLock.cs @@ -0,0 +1,23 @@ +using System.Runtime.CompilerServices; + +namespace Hyperbar; + +public class AsyncLock(int initial = 1, + int maximum = 1) : + IDisposable +{ + private readonly SemaphoreSlim semaphore = new(initial, maximum); + + public void Dispose() + { + semaphore.Release(); + } + + public TaskAwaiter GetAwaiter() => LockAsync().GetAwaiter(); + + private async Task LockAsync() + { + await semaphore.WaitAsync(); + return this; + } +} diff --git a/Hyperbar/Lifecycles/Cache.cs b/Hyperbar/Lifecycles/Cache.cs index 2ef2866..749cbbf 100644 --- a/Hyperbar/Lifecycles/Cache.cs +++ b/Hyperbar/Lifecycles/Cache.cs @@ -11,24 +11,25 @@ public class Cache(IDisposer disposer) : public void Add(TValue value) { - disposer.Add(value!, Disposable.Create(() => + if (value is null) { - Remove(value); - })); + return; + } + disposer.Add(value, Disposable.Create(() => Remove(value))); cache.Add(value); } public void Clear() => cache.Clear(); - public System.Collections.Generic.IEnumerator GetEnumerator() => cache.GetEnumerator(); + public IEnumerator GetEnumerator() => cache.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public bool Remove(TValue value) => cache.Remove(value); } -public class Cache(IDisposer disposer) : +public class Cache : ICache where TKey : notnull @@ -47,7 +48,7 @@ public class Cache(IDisposer disposer) : public bool ContainsKey(TKey key) => cache.ContainsKey(key); - public System.Collections.Generic.IEnumerator> GetEnumerator() => cache.GetEnumerator(); + public IEnumerator> GetEnumerator() => cache.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/Hyperbar/Lifecycles/Disposer.cs b/Hyperbar/Lifecycles/Disposer.cs index d223980..3de0207 100644 --- a/Hyperbar/Lifecycles/Disposer.cs +++ b/Hyperbar/Lifecycles/Disposer.cs @@ -1,30 +1,9 @@ -using System.Runtime.CompilerServices; -using System.Reactive.Disposables; +using System.Reactive.Disposables; using System.Collections; using System.Collections.Concurrent; namespace Hyperbar; -public class AsyncLock(int initial = 1, - int maximum = 1) : IDisposable -{ - private readonly SemaphoreSlim semaphore = new(initial, maximum); - - public void Dispose() - { - semaphore.Release(); - } - - public TaskAwaiter GetAwaiter() => LockAsync().GetAwaiter(); - - private async Task LockAsync() - { - await semaphore.WaitAsync(); - return this; - } -} - - public class Disposer : IDisposer { diff --git a/Hyperbar/Lifecycles/IEnumerator.cs b/Hyperbar/Lifecycles/IEnumerator.cs deleted file mode 100644 index f95353c..0000000 --- a/Hyperbar/Lifecycles/IEnumerator.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Hyperbar; - -public interface IEnumerator -{ - IEnumerable Get(); -} diff --git a/Hyperbar/Lifecycles/IObservableViewModel.cs b/Hyperbar/Lifecycles/IObservableViewModel.cs index 87eb6bf..3c13ef5 100644 --- a/Hyperbar/Lifecycles/IObservableViewModel.cs +++ b/Hyperbar/Lifecycles/IObservableViewModel.cs @@ -6,7 +6,7 @@ public interface IObservableViewModel : { public IDisposer Disposer { get; } - public IMediator Mediator { get; } + public IPublisher Publisher { get; } public IServiceFactory ServiceFactory { get; } diff --git a/Hyperbar/Lifecycles/Navigate.cs b/Hyperbar/Lifecycles/Navigate.cs index fb8143b..4865f58 100644 --- a/Hyperbar/Lifecycles/Navigate.cs +++ b/Hyperbar/Lifecycles/Navigate.cs @@ -4,5 +4,5 @@ namespace Hyperbar; public record Navigate(object Key) : INotification; -public record Navigate(TTemplate Template, object Content) : +public record Navigate(TView View, object ViewModel) : INotification; diff --git a/Hyperbar/Lifecycles/NavigateHandler.cs b/Hyperbar/Lifecycles/NavigateHandler.cs index c249d07..50cb2fa 100644 --- a/Hyperbar/Lifecycles/NavigateHandler.cs +++ b/Hyperbar/Lifecycles/NavigateHandler.cs @@ -7,16 +7,16 @@ public class NavigateHandler : { private readonly IViewModelTemplateDescriptorProvider contentTemplateDescriptors; private readonly IServiceProvider provider; - private readonly IMediator mediator; + private readonly IPublisher publisher; private readonly IEnumerable navigationDescriptors; public NavigateHandler(IServiceProvider provider, - IMediator mediator, + IPublisher publisher, IEnumerable navigationDescriptors, IViewModelTemplateDescriptorProvider contentTemplateDescriptors) { this.provider = provider; - this.mediator = mediator; + this.publisher = publisher; this.navigationDescriptors = navigationDescriptors; this.contentTemplateDescriptors = contentTemplateDescriptors; } @@ -43,7 +43,7 @@ public class NavigateHandler : if (Activator.CreateInstance(navigateType, new object[] { template, content }) is object navigate) { - await mediator.PublishAsync(navigate, cancellationToken); + await publisher.PublishAsync(navigate, cancellationToken); } } } diff --git a/Hyperbar/Lifecycles/NavigationViewModel.cs b/Hyperbar/Lifecycles/NavigationViewModel.cs index 1f70282..27f4fa5 100644 --- a/Hyperbar/Lifecycles/NavigationViewModel.cs +++ b/Hyperbar/Lifecycles/NavigationViewModel.cs @@ -2,29 +2,26 @@ namespace Hyperbar; -public partial class NavigationViewModel : - ObservableCollectionViewModel, +public partial class NavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + string text) : + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), INavigationViewModel { [ObservableProperty] - private string? text; - - public NavigationViewModel(IServiceProvider serviceProvider, - IServiceFactory serviceFactory, - IMediator mediator, - IDisposer disposer, - string text) : base(serviceProvider, serviceFactory, mediator, disposer) - { - this.text = text; - } + private string? text = text; } public partial class NavigationViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, string text) : - ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer), + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), INavigationViewModel where TNavigationViewModel : INavigationViewModel diff --git a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs index cd0f29f..9e96b63 100644 --- a/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs +++ b/Hyperbar/Lifecycles/ObservableCollectionViewModel.cs @@ -27,31 +27,33 @@ public partial class ObservableCollectionViewModel : public ObservableCollectionViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer) { ServiceProvider = serviceProvider; ServiceFactory = serviceFactory; - Mediator = mediator; + Publisher = publisher; Disposer = disposer; - mediator.Subscribe(this); + subscriber.Add(this); collection.CollectionChanged += OnCollectionChanged; } public ObservableCollectionViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer, IEnumerable items) { ServiceProvider = serviceProvider; ServiceFactory = serviceFactory; - Mediator = mediator; + Publisher = publisher; Disposer = disposer; - mediator.Subscribe(this); + subscriber.Add(this); collection.CollectionChanged += OnCollectionChanged; AddRange(items); @@ -74,14 +76,14 @@ public partial class ObservableCollectionViewModel : bool ICollection.IsSynchronized => false; - public IMediator Mediator { get; private set; } + public IPublisher Publisher { get; private set; } public IServiceFactory ServiceFactory { get; private set; } - object ICollection.SyncRoot => this; - public IServiceProvider ServiceProvider { get; private set; } + object ICollection.SyncRoot => this; + public TViewModel this[int index] { get => collection[index]; @@ -374,7 +376,7 @@ public partial class ObservableCollectionViewModel : isInitialized = true; - await Mediator.PublishAsync>(); + await Publisher.PublishAsync>(); await InitializeAsync(); } @@ -384,6 +386,7 @@ public partial class ObservableCollectionViewModel : public class ObservableCollectionViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, + ISubscriber subscriber, IDisposer disposer) : - ObservableCollectionViewModel(serviceProvider, serviceFactory, mediator, disposer); \ No newline at end of file + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer); \ No newline at end of file diff --git a/Hyperbar/Lifecycles/ObservableViewModel.cs b/Hyperbar/Lifecycles/ObservableViewModel.cs index 307340d..6410c8c 100644 --- a/Hyperbar/Lifecycles/ObservableViewModel.cs +++ b/Hyperbar/Lifecycles/ObservableViewModel.cs @@ -6,7 +6,7 @@ namespace Hyperbar; public class ObservableViewModel(IServiceProvider serviceProvider, IServiceFactory serviceFactory, - IMediator mediator, + IPublisher publisher, IDisposer disposer) : ObservableObject, IObservableViewModel @@ -16,9 +16,9 @@ public class ObservableViewModel(IServiceProvider serviceProvider, public IDisposer Disposer => disposer; public ICommand InitializeCommand => - new AsyncRelayCommand(CoreInitializeAsync); + new AsyncRelayCommand(CoreInitializeAsync); - public IMediator Mediator => mediator; + public IPublisher Publisher => publisher; public IServiceFactory ServiceFactory => serviceFactory; diff --git a/Hyperbar/Mediators/HandlerDelegate.cs b/Hyperbar/Mediators/HandlerDelegate.cs index dfd4744..2240cf1 100644 --- a/Hyperbar/Mediators/HandlerDelegate.cs +++ b/Hyperbar/Mediators/HandlerDelegate.cs @@ -3,5 +3,4 @@ public delegate Task HandlerDelegate(TMessage message, CancellationToken cancellationToken) where TMessage : - notnull, IMessage; \ No newline at end of file diff --git a/Hyperbar/Mediators/HandlerWrapper.cs b/Hyperbar/Mediators/HandlerWrapper.cs index 5b51b03..a64f61d 100644 --- a/Hyperbar/Mediators/HandlerWrapper.cs +++ b/Hyperbar/Mediators/HandlerWrapper.cs @@ -1,27 +1,25 @@ namespace Hyperbar; -public class HandlerWrapper - where TRequest : - class, - IRequest +public class HandlerWrapper(IHandler handler, + IEnumerable> pipelineBehaviours) + where TMessage : class, IRequest { - private readonly HandlerDelegate handler; + private readonly IEnumerable> pipelineBehaviours = + pipelineBehaviours.Reverse(); - public HandlerWrapper(IHandler concreteHandler, - IEnumerable> pipelineBehaviours) + public async Task Handle(TMessage message, CancellationToken cancellationToken) { - HandlerDelegate handler = concreteHandler.Handle; - foreach (IPipelineBehavior? pipeline in pipelineBehaviours.Reverse()) + HandlerDelegate currentHandler = handler.Handle; + foreach (IPipelineBehavior behavior in pipelineBehaviours) { - HandlerDelegate handlerCopy = handler; - IPipelineBehavior pipelineCopy = pipeline; - - handler = (TRequest message, CancellationToken cancellationToken) => - pipelineCopy.Handle(message, handlerCopy, cancellationToken); + HandlerDelegate previousHandler = currentHandler; + currentHandler = async (msg, token) => + { + return await behavior.Handle(msg, previousHandler, token); + }; } - this.handler = handler; + return await currentHandler(message, cancellationToken); } +} - public Task Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken); -} \ No newline at end of file diff --git a/Hyperbar/Mediators/IMediator.cs b/Hyperbar/Mediators/IMediator.cs index a800ac0..8a3ff41 100644 --- a/Hyperbar/Mediators/IMediator.cs +++ b/Hyperbar/Mediators/IMediator.cs @@ -2,41 +2,9 @@ public interface IMediator { - Task PublishAsync(TNotification notification, - object key, - CancellationToken cancellationToken = default) - where TNotification : - INotification; - - Task PublishAsync(object key, - CancellationToken cancellationToken = default) - where TNotification : - INotification, - new(); - - Task PublishAsync(TNotification notification, - CancellationToken cancellationToken = default) - where TNotification : - INotification; - - Task PublishAsync(object notification, - CancellationToken cancellationToken = default); - - Task PublishAsync(object notification, - Func, Task> marshal, - object? key = null, - CancellationToken cancellationToken = default); - - Task PublishAsync(CancellationToken cancellationToken = default) - where TNotification : - INotification, - new(); - Task SendAsync(IRequest request, CancellationToken cancellationToken = default); Task SendAsync(object message, CancellationToken cancellationToken = default); - - void Subscribe(object handler); } \ No newline at end of file diff --git a/Hyperbar/Mediators/INotification.cs b/Hyperbar/Mediators/INotification.cs index 9fc54c3..a203ded 100644 --- a/Hyperbar/Mediators/INotification.cs +++ b/Hyperbar/Mediators/INotification.cs @@ -1,3 +1,4 @@ namespace Hyperbar; -public interface INotification : IMessage; \ No newline at end of file +public interface INotification : + IMessage; \ No newline at end of file diff --git a/Hyperbar/Mediators/IPublisher.cs b/Hyperbar/Mediators/IPublisher.cs new file mode 100644 index 0000000..0c615d5 --- /dev/null +++ b/Hyperbar/Mediators/IPublisher.cs @@ -0,0 +1,34 @@ +namespace Hyperbar; + +public interface IPublisher +{ + Task PublishAsync(TNotification notification, + object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification; + + Task PublishAsync(object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification, + new(); + + Task PublishAsync(TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : + INotification; + + Task PublishAsync(object notification, + CancellationToken cancellationToken = default); + + Task PublishAsync(object notification, + Func, Task> marshal, + object? key = null, + CancellationToken cancellationToken = default); + + Task PublishAsync(CancellationToken cancellationToken = default) + where TNotification : + INotification, + new(); +} diff --git a/Hyperbar/Mediators/ISubscriber.cs b/Hyperbar/Mediators/ISubscriber.cs new file mode 100644 index 0000000..becc10b --- /dev/null +++ b/Hyperbar/Mediators/ISubscriber.cs @@ -0,0 +1,8 @@ +namespace Hyperbar; + +public interface ISubscriber +{ + void Remove(object subscriber); + + void Add(object subscriber); +} \ No newline at end of file diff --git a/Hyperbar/Mediators/ISubscriptionManager.cs b/Hyperbar/Mediators/ISubscriptionManager.cs new file mode 100644 index 0000000..30e4f39 --- /dev/null +++ b/Hyperbar/Mediators/ISubscriptionManager.cs @@ -0,0 +1,10 @@ +namespace Hyperbar; + +public interface ISubscriptionManager +{ + IEnumerable GetHandlers(Type notificationType, object key); + + void Remove(object subscriber); + + void Add(object subscriber); +} diff --git a/Hyperbar/Mediators/Mediator.cs b/Hyperbar/Mediators/Mediator.cs index 0b2a812..8436213 100644 --- a/Hyperbar/Mediators/Mediator.cs +++ b/Hyperbar/Mediators/Mediator.cs @@ -1,91 +1,8 @@ -using Microsoft.Extensions.DependencyInjection; -using System.Collections.Concurrent; -using System.Reflection; +namespace Hyperbar; -namespace Hyperbar; - -public class Mediator(IServiceProvider provider, - IDispatcher dispatcher) : +public class Mediator(IServiceProvider provider) : IMediator { - private readonly ConcurrentDictionary> handlers = []; - - public Task PublishAsync(object key, - CancellationToken cancellationToken = default) - where TNotification : - INotification, - new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()), - key, cancellationToken); - - public Task PublishAsync(TNotification notification, - CancellationToken cancellationToken = default) - where TNotification : - INotification - { - return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), - null, cancellationToken); - } - - public Task PublishAsync(TNotification notification, - object key, - CancellationToken cancellationToken = default) - where TNotification : - INotification - { - return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), - key, cancellationToken); - } - - public Task PublishAsync(object notification, - Func, Task> marshal, - object? key = null, - CancellationToken cancellationToken = default) - { - Type notificationType = notification.GetType(); - - List handlers = provider.GetServices(typeof(INotificationHandler<>) - .MakeGenericType(notificationType)).ToList(); - - foreach (KeyValuePair> subscriber in this.handlers) - { - if (subscriber.Key.Equals($"{key?.ToString()}:{notificationType}")) - { - handlers.AddRange(subscriber.Value); - } - } - - foreach (object? handler in handlers) - { - if (handler is not null) - { - Type? handlerType = handler.GetType(); - MethodInfo? handleMethod = handlerType.GetMethod("Handle", - [notificationType, typeof(CancellationToken)]); - - if (handleMethod is not null) - { - marshal(() => (Task)handleMethod.Invoke(handler, new object[] { notification, - cancellationToken })!); - } - } - } - - return Task.CompletedTask; - } - - public Task PublishAsync(CancellationToken cancellationToken = default) - where TNotification : - INotification, - new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()), - null, cancellationToken); - - public Task PublishAsync(object notification, - CancellationToken cancellationToken = default) - { - return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), - null, cancellationToken); - } - public Task SendAsync(IRequest request, CancellationToken cancellationToken = default) { @@ -121,44 +38,4 @@ public class Mediator(IServiceProvider provider, return Task.FromResult(default); } - - public void Subscribe(object handler) - { - Type handlerType = handler.GetType(); - object? key = GetKeyFromHandler(handlerType, handler); - - foreach (Type interfaceType in GetNotificationHandlerInterfaces(handlerType)) - { - if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) - { - handlers.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", new List { handler }, (value, collection) => - { - collection.Add(handler); - return collection; - }); - } - } - } - - private object? GetKeyFromHandler(Type handlerType, object handler) - { - if (handlerType.GetCustomAttribute() is NotificationHandlerAttribute attribute) - { - if (handlerType.GetProperty($"{attribute.Key}") is PropertyInfo property - && property.GetValue(handler) is { } value) - { - return value; - } - else - { - return attribute.Key; - } - } - - return null; - } - - private IEnumerable GetNotificationHandlerInterfaces(Type handlerType) => handlerType.GetInterfaces() - .Where(interfaceType => interfaceType.IsGenericType && interfaceType - .GetGenericTypeDefinition() == typeof(INotificationHandler<>)); } \ No newline at end of file diff --git a/Hyperbar/Mediators/NotficationRelayHandler.cs b/Hyperbar/Mediators/NotficationRelayHandler.cs deleted file mode 100644 index 73f98f3..0000000 --- a/Hyperbar/Mediators/NotficationRelayHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ - -namespace Hyperbar; - -public class NotficationRelayHandler(IMediator mediator) : - INotificationHandler, - IHandler - where TFromNotification : - INotification - where ToNotification : - INotification, new() -{ - private readonly IMediator mediator = mediator; - - public Task Handle(TFromNotification notification, CancellationToken cancellationToken) => - mediator.PublishAsync(cancellationToken); -} \ No newline at end of file diff --git a/Hyperbar/Mediators/Publisher.cs b/Hyperbar/Mediators/Publisher.cs new file mode 100644 index 0000000..e5cdf57 --- /dev/null +++ b/Hyperbar/Mediators/Publisher.cs @@ -0,0 +1,84 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Reflection; + +namespace Hyperbar; + +public class Publisher(ISubscriptionManager subscriptionManager, + IServiceProvider provider, + IDispatcher dispatcher) : + IPublisher +{ + public Task PublishAsync(object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification, + new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()), + key, cancellationToken); + + public Task PublishAsync(TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : + INotification + { + return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), + null, cancellationToken); + } + + public Task PublishAsync(TNotification notification, + object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification + { + return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), + key, cancellationToken); + } + + public Task PublishAsync(object notification, + Func, Task> marshal, + object? key = null, + CancellationToken cancellationToken = default) + { + Type notificationType = notification.GetType(); + List handlers = provider.GetServices(typeof(INotificationHandler<>) + .MakeGenericType(notificationType)).ToList(); + + foreach (object? handler in subscriptionManager.GetHandlers(notificationType, + $"{key?.ToString()}:{notificationType}")) + { + handlers.Add(handler); + } + + foreach (object? handler in handlers) + { + if (handler is not null) + { + Type? handlerType = handler.GetType(); + MethodInfo? handleMethod = handlerType.GetMethod("Handle", + [notificationType, typeof(CancellationToken)]); + + if (handleMethod is not null) + { + marshal(() => (Task)handleMethod.Invoke(handler, new object[] { notification, + cancellationToken })!); + } + } + } + + return Task.CompletedTask; + } + + public Task PublishAsync(CancellationToken cancellationToken = default) + where TNotification : + INotification, + new() => PublishAsync(new TNotification(), args => dispatcher.InvokeAsync(async () => await args()), + null, cancellationToken); + + public Task PublishAsync(object notification, + CancellationToken cancellationToken = default) + { + return PublishAsync(notification, args => dispatcher.InvokeAsync(async () => await args()), + null, cancellationToken); + } + +} diff --git a/Hyperbar/Mediators/Subscriber.cs b/Hyperbar/Mediators/Subscriber.cs new file mode 100644 index 0000000..8d50e92 --- /dev/null +++ b/Hyperbar/Mediators/Subscriber.cs @@ -0,0 +1,11 @@ +namespace Hyperbar; + +public class Subscriber(ISubscriptionManager subscriptionManager) : + ISubscriber +{ + public void Remove(object subscriber) => + subscriptionManager.Remove(subscriber); + + public void Add(object subscriber) => + subscriptionManager.Add(subscriber); +} \ No newline at end of file diff --git a/Hyperbar/Mediators/Subscription.cs b/Hyperbar/Mediators/Subscription.cs new file mode 100644 index 0000000..ce347ff --- /dev/null +++ b/Hyperbar/Mediators/Subscription.cs @@ -0,0 +1,3 @@ +namespace Hyperbar; + +public record Subscription(object Handler); diff --git a/Hyperbar/Mediators/SubscriptionManager.cs b/Hyperbar/Mediators/SubscriptionManager.cs new file mode 100644 index 0000000..6f93535 --- /dev/null +++ b/Hyperbar/Mediators/SubscriptionManager.cs @@ -0,0 +1,90 @@ +using System.Collections.Concurrent; +using System.Reflection; + +namespace Hyperbar; + +public class SubscriptionManager : + ISubscriptionManager +{ + private readonly ConcurrentDictionary> subscriptions = new(); + + public IEnumerable GetHandlers(Type notificationType, object key) + { + if (subscriptions.TryGetValue($"{key?.ToString()}:{notificationType}", + out List? subscribers)) + { + foreach (WeakReference weakRef in subscribers.ToArray()) + { + object? target = weakRef.Target; + if (target != null) + { + yield return target; + } + else + { + subscribers.Remove(weakRef); + } + } + } + } + + public void Remove(object subscriber) + { + Type handlerType = subscriber.GetType(); + object? key = GetKeyFromHandler(handlerType, subscriber); + foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) + { + if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) + { + if (subscriptions.TryGetValue($"{(key is not null ? $"{key}:" : "")}{argumentType}", out List? subscribers)) + { + for (int i = subscribers.Count - 1; i >= 0; i--) + { + if (!subscribers[i].IsAlive || subscribers[i].Target == subscriber) + { + subscribers.RemoveAt(i); + } + } + } + } + } + } + + public void Add(object subscriber) + { + Type handlerType = subscriber.GetType(); + object? key = GetKeyFromHandler(handlerType, subscriber); + foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) + { + if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) + { + subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", _ => new List { new WeakReference(subscriber) }, (_, collection) => + { + collection.Add(new WeakReference(subscriber)); + return collection; + }); + } + } + } + + private static object? GetKeyFromHandler(Type handlerType, object handler) + { + if (handlerType.GetCustomAttribute() is NotificationHandlerAttribute attribute) + { + if (handlerType.GetProperty($"{attribute.Key}") is PropertyInfo property + && property.GetValue(handler) is { } value) + { + return value; + } + else + { + return attribute.Key; + } + } + return null; + } + + private static IEnumerable GetHandlerInterfaces(Type handlerType) => + handlerType.GetInterfaces().Where(interfaceType => interfaceType.IsGenericType && + interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)); +}