Use single subscriber tab for replies
This commit is contained in:
parent
6e8029b552
commit
76d4c8fa85
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace PettingZoo.Core.Connection
|
||||
{
|
||||
public interface ISubscriber : IAsyncDisposable
|
||||
public interface ISubscriber : IDisposable
|
||||
{
|
||||
string? QueueName { get; }
|
||||
string? Exchange {get; }
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using PettingZoo.Core.Connection;
|
||||
|
||||
namespace PettingZoo.Core.ExportImport
|
||||
@ -13,7 +12,10 @@ namespace PettingZoo.Core.ExportImport
|
||||
public string? QueueName { get; }
|
||||
public string? Exchange => null;
|
||||
public string? RoutingKey => null;
|
||||
|
||||
#pragma warning disable CS0067 // "The event ... is never used" - it's part of the interface so it's required.
|
||||
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||
#pragma warning restore CS0067
|
||||
|
||||
|
||||
public ImportSubscriber(string filename, IReadOnlyList<ReceivedMessageInfo> messages)
|
||||
@ -23,10 +25,9 @@ namespace PettingZoo.Core.ExportImport
|
||||
}
|
||||
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
return default;
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace PettingZoo.Core.ExportImport
|
||||
public StreamWrapper(StreamProgressDecorator owner, Stream decoratedStream)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.DecoratedStream = decoratedStream;
|
||||
DecoratedStream = decoratedStream;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using PettingZoo.Core.Connection;
|
||||
using RabbitMQ.Client;
|
||||
using RabbitMQ.Client.Events;
|
||||
@ -29,14 +28,12 @@ namespace PettingZoo.RabbitMQ
|
||||
}
|
||||
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
if (model != null && consumerTag != null && model.IsOpen)
|
||||
model.BasicCancelNoWait(consumerTag);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
|
||||
|
@ -5,7 +5,6 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.Core.Settings;
|
||||
using PettingZoo.Tapeti.AssemblyLoader;
|
||||
|
@ -4,9 +4,6 @@
|
||||
|
||||
Should-have
|
||||
-----------
|
||||
- Single tab for responses, don't create a new subscriber tab for 1 message each time
|
||||
Use the CorrelationId in the list for such cases instead of the routing key (which is the name of the dynamic queue for the responses).
|
||||
Set the CorrelationId to the request routing key for example, so the different responses can be somewhat identified.
|
||||
|
||||
|
||||
Nice-to-have
|
||||
|
@ -170,7 +170,7 @@ namespace PettingZoo.UI.Main
|
||||
if (connectionSettings.Subscribe)
|
||||
{
|
||||
var subscriber = connection.Subscribe(connectionSettings.Exchange, connectionSettings.RoutingKey);
|
||||
AddTab(tabFactory.CreateSubscriberTab(connection, subscriber));
|
||||
tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||
}
|
||||
|
||||
ConnectionChanged();
|
||||
@ -214,7 +214,7 @@ namespace PettingZoo.UI.Main
|
||||
subscribeDialogParams = newParams;
|
||||
|
||||
var subscriber = connection.Subscribe(subscribeDialogParams.Exchange, subscribeDialogParams.RoutingKey);
|
||||
AddTab(tabFactory.CreateSubscriberTab(connection, subscriber));
|
||||
tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||
}
|
||||
|
||||
|
||||
@ -223,7 +223,7 @@ namespace PettingZoo.UI.Main
|
||||
if (connection == null)
|
||||
return;
|
||||
|
||||
AddTab(tabFactory.CreatePublisherTab(connection));
|
||||
tabFactory.CreatePublisherTab(connection);
|
||||
}
|
||||
|
||||
|
||||
@ -235,7 +235,8 @@ namespace PettingZoo.UI.Main
|
||||
|
||||
private void CloseTabExecute()
|
||||
{
|
||||
RemoveActiveTab();
|
||||
var tab = RemoveActiveTab();
|
||||
(tab as IDisposable)?.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@ -300,8 +301,7 @@ namespace PettingZoo.UI.Main
|
||||
progressWindow.Close();
|
||||
progressWindow = null;
|
||||
|
||||
AddTab(tabFactory.CreateSubscriberTab(connection,
|
||||
new ImportSubscriber(filename, messages)));
|
||||
tabFactory.CreateSubscriberTab(connection, new ImportSubscriber(filename, messages));
|
||||
});
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@ -377,6 +377,15 @@ namespace PettingZoo.UI.Main
|
||||
}
|
||||
|
||||
|
||||
public void ActivateTab(ITab tab)
|
||||
{
|
||||
if (undockedTabs.TryGetValue(tab, out var window))
|
||||
window.Activate();
|
||||
else if (Tabs.Contains(tab))
|
||||
ActiveTab = tab;
|
||||
}
|
||||
|
||||
|
||||
public void DockTab(ITab tab)
|
||||
{
|
||||
if (undockedTabs.Remove(tab, out var tabHostWindow))
|
||||
|
@ -2,13 +2,10 @@
|
||||
|
||||
namespace PettingZoo.UI.Tab
|
||||
{
|
||||
// Passing the closeTabCommand is necessary because I haven't figured out how to bind the main window's
|
||||
// context menu items for the tab to the main window's datacontext yet. RelativeSource doesn't seem to work
|
||||
// because the popup is it's own window. Refactor if a better solution is found.
|
||||
|
||||
public interface ITabFactory
|
||||
{
|
||||
ITab CreateSubscriberTab(IConnection? connection, ISubscriber subscriber);
|
||||
ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null);
|
||||
void CreateSubscriberTab(IConnection? connection, ISubscriber subscriber);
|
||||
string CreateReplySubscriberTab(IConnection connection);
|
||||
void CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
public interface ITabHost
|
||||
{
|
||||
void AddTab(ITab tab);
|
||||
void ActivateTab(ITab tab);
|
||||
|
||||
void DockTab(ITab tab);
|
||||
void UndockedTabClosed(ITab tab);
|
||||
|
@ -5,6 +5,6 @@
|
||||
string Exchange { get; }
|
||||
string RoutingKey { get; }
|
||||
|
||||
string? GetReplyTo();
|
||||
string? GetReplyTo(ref string? correlationId);
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
private readonly IConnection connection;
|
||||
private readonly IExampleGenerator exampleGenerator;
|
||||
private readonly ITabFactory tabFactory;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
|
||||
private bool sendToExchange = true;
|
||||
private string exchange = "";
|
||||
@ -156,12 +155,11 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
string IPublishDestination.RoutingKey => SendToExchange ? RoutingKey : Queue;
|
||||
|
||||
|
||||
public PublisherViewModel(ITabHostProvider tabHostProvider, ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
public PublisherViewModel(ITabFactory tabFactory, IConnection connection, IExampleGenerator exampleGenerator, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
{
|
||||
this.connection = connection;
|
||||
this.exampleGenerator = exampleGenerator;
|
||||
this.tabFactory = tabFactory;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
|
||||
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||
|
||||
@ -280,17 +278,13 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
}
|
||||
|
||||
|
||||
public string? GetReplyTo()
|
||||
public string? GetReplyTo(ref string? correlationId)
|
||||
{
|
||||
if (ReplyToSpecified)
|
||||
return string.IsNullOrEmpty(ReplyTo) ? null : ReplyTo;
|
||||
|
||||
var subscriber = connection.Subscribe();
|
||||
var tab = tabFactory.CreateSubscriberTab(connection, subscriber);
|
||||
tabHostProvider.Instance.AddTab(tab);
|
||||
|
||||
subscriber.Start();
|
||||
return subscriber.QueueName;
|
||||
correlationId = SendToExchange ? RoutingKey : Queue;
|
||||
return tabFactory.CreateReplySubscriberTab(connection);
|
||||
}
|
||||
|
||||
|
||||
@ -305,7 +299,7 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
public class DesignTimePublisherViewModel : PublisherViewModel
|
||||
{
|
||||
public DesignTimePublisherViewModel() : base(null!, null!, null!, null!)
|
||||
public DesignTimePublisherViewModel() : base(null!, null!, null!)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -244,6 +244,8 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
|
||||
|
||||
var headers = Headers.Where(h => h.IsValid()).ToDictionary(h => h.Key, h => h.Value);
|
||||
var publishCorrelationId = NullIfEmpty(CorrelationId);
|
||||
var replyTo = publishDestination.GetReplyTo(ref publishCorrelationId);
|
||||
|
||||
connection.Publish(new PublishMessageInfo(
|
||||
publishDestination.Exchange,
|
||||
@ -254,12 +256,12 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
AppId = NullIfEmpty(AppId),
|
||||
ContentEncoding = NullIfEmpty(ContentEncoding),
|
||||
ContentType = NullIfEmpty(ContentType),
|
||||
CorrelationId = NullIfEmpty(CorrelationId),
|
||||
CorrelationId = publishCorrelationId,
|
||||
DeliveryMode = deliveryMode,
|
||||
Expiration = NullIfEmpty(Expiration),
|
||||
MessageId = NullIfEmpty(MessageId),
|
||||
Priority = priorityValue,
|
||||
ReplyTo = publishDestination.GetReplyTo(),
|
||||
ReplyTo = replyTo,
|
||||
Timestamp = timestampValue,
|
||||
Type = NullIfEmpty(TypeProperty),
|
||||
UserId = NullIfEmpty(UserId)
|
||||
|
@ -2,7 +2,6 @@
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.Core.Validation;
|
||||
@ -151,7 +150,10 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
{
|
||||
return string.IsNullOrEmpty(value) ? null : value;
|
||||
}
|
||||
|
||||
|
||||
var publishCorrelationId = NullIfEmpty(CorrelationId);
|
||||
var replyTo = publishDestination.GetReplyTo(ref publishCorrelationId);
|
||||
|
||||
connection.Publish(new PublishMessageInfo(
|
||||
publishDestination.Exchange,
|
||||
publishDestination.RoutingKey,
|
||||
@ -162,9 +164,9 @@ namespace PettingZoo.UI.Tab.Publisher
|
||||
})
|
||||
{
|
||||
ContentType = @"application/json",
|
||||
CorrelationId = NullIfEmpty(CorrelationId),
|
||||
CorrelationId = publishCorrelationId,
|
||||
DeliveryMode = MessageDeliveryMode.Persistent,
|
||||
ReplyTo = publishDestination.GetReplyTo()
|
||||
ReplyTo = replyTo
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
public class SameMessageVisibilityConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return ReferenceEquals(values[0], values[1])
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -13,9 +13,6 @@
|
||||
d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance res:DesignTimeSubscriberViewModel, IsDesignTimeCreatable=True}"
|
||||
Background="White">
|
||||
<UserControl.Resources>
|
||||
<res:SameMessageVisibilityConverter x:Key="SameMessageVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
<Grid Margin="4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
@ -64,7 +61,10 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0" Text="{Binding ReceivedTimestamp, StringFormat=g}" Style="{StaticResource Timestamp}" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}" />
|
||||
<!-- ReSharper disable Xaml.BindingWithContextNotResolved -->
|
||||
<TextBlock Grid.Column="1" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}" Visibility="{Binding Data.StandardTabVisibility, Source={StaticResource ContextMenuProxy}}" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding Properties.CorrelationId}" Style="{StaticResource RoutingKey}" Visibility="{Binding Data.ReplyToTabVisibility, Source={StaticResource ContextMenuProxy}}" />
|
||||
<!-- ReSharper restore Xaml.BindingWithContextNotResolved -->
|
||||
|
||||
<Grid.ContextMenu>
|
||||
<ContextMenu>
|
||||
|
@ -21,10 +21,9 @@ using Timer = System.Threading.Timer;
|
||||
|
||||
namespace PettingZoo.UI.Tab.Subscriber
|
||||
{
|
||||
public class SubscriberViewModel : BaseViewModel, ITabToolbarCommands, ITabActivate
|
||||
public class SubscriberViewModel : BaseViewModel, IDisposable, ITabToolbarCommands, ITabActivate
|
||||
{
|
||||
private readonly ILogger logger;
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
private readonly ITabFactory tabFactory;
|
||||
private readonly IConnection? connection;
|
||||
private readonly ISubscriber subscriber;
|
||||
@ -76,16 +75,43 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
set => SetField(ref selectedMessageProperties, value);
|
||||
}
|
||||
|
||||
public string Title =>
|
||||
(subscriber.Exchange != null ? $"{subscriber.Exchange} - {subscriber.RoutingKey}" : $"{subscriber.QueueName}") +
|
||||
(tabActive || unreadCount == 0 ? "" : $" ({unreadCount})");
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
var title = new StringBuilder();
|
||||
|
||||
if (IsReplyTab)
|
||||
title.Append(SubscriberViewStrings.ReplyTabTitle);
|
||||
else if (subscriber.Exchange != null)
|
||||
title.Append(subscriber.Exchange).Append(" - ").Append(subscriber.RoutingKey);
|
||||
else
|
||||
title.Append(subscriber.QueueName);
|
||||
|
||||
if (!tabActive && unreadCount > 0)
|
||||
title.Append(" (").Append(unreadCount).Append(')');
|
||||
|
||||
return title.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
||||
|
||||
|
||||
public SubscriberViewModel(ILogger logger, ITabHostProvider tabHostProvider, ITabFactory tabFactory, IConnection? connection, ISubscriber subscriber, IExportImportFormatProvider exportImportFormatProvider)
|
||||
public bool IsReplyTab { get; }
|
||||
|
||||
// ReSharper disable UnusedMember.Global - used via BindingProxy
|
||||
public Visibility StandardTabVisibility => !IsReplyTab ? Visibility.Visible : Visibility.Collapsed;
|
||||
public Visibility ReplyTabVisibility => IsReplyTab ? Visibility.Visible : Visibility.Collapsed;
|
||||
// ReSharper restore UnusedMember.Global
|
||||
|
||||
|
||||
public SubscriberViewModel(ILogger logger, ITabFactory tabFactory, IConnection? connection, ISubscriber subscriber, IExportImportFormatProvider exportImportFormatProvider, bool isReplyTab)
|
||||
{
|
||||
IsReplyTab = isReplyTab;
|
||||
|
||||
this.logger = logger;
|
||||
this.tabHostProvider = tabHostProvider;
|
||||
this.tabFactory = tabFactory;
|
||||
this.connection = connection;
|
||||
this.subscriber = subscriber;
|
||||
@ -111,6 +137,15 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
subscriber.Start();
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
newMessageTimer?.Dispose();
|
||||
subscriber.Dispose();
|
||||
}
|
||||
|
||||
|
||||
private void ClearExecute()
|
||||
{
|
||||
Messages.Clear();
|
||||
@ -222,8 +257,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
if (connection == null)
|
||||
return;
|
||||
|
||||
var publisherTab = tabFactory.CreatePublisherTab(connection, SelectedMessage);
|
||||
tabHostProvider.Instance.AddTab(publisherTab);
|
||||
tabFactory.CreatePublisherTab(connection, SelectedMessage);
|
||||
}
|
||||
|
||||
|
||||
@ -320,7 +354,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
|
||||
public class DesignTimeSubscriberViewModel : SubscriberViewModel
|
||||
{
|
||||
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, null!, new DesignTimeSubscriber(), null!)
|
||||
public DesignTimeSubscriberViewModel() : base(null!, null!, null!, new DesignTimeSubscriber(), null!, false)
|
||||
{
|
||||
for (var i = 1; i <= 5; i++)
|
||||
(i > 2 ? UnreadMessages : Messages).Add(new ReceivedMessageInfo(
|
||||
@ -340,9 +374,9 @@ namespace PettingZoo.UI.Tab.Subscriber
|
||||
|
||||
private class DesignTimeSubscriber : ISubscriber
|
||||
{
|
||||
public ValueTask DisposeAsync()
|
||||
public void Dispose()
|
||||
{
|
||||
return default;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,5 +185,14 @@ namespace PettingZoo.UI.Tab.Subscriber {
|
||||
return ResourceManager.GetString("PropertyValue", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Replies.
|
||||
/// </summary>
|
||||
public static string ReplyTabTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ReplyTabTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,4 +159,7 @@
|
||||
<data name="PropertyValue" xml:space="preserve">
|
||||
<value>Value</value>
|
||||
</data>
|
||||
<data name="ReplyTabTitle" xml:space="preserve">
|
||||
<value>Replies</value>
|
||||
</data>
|
||||
</root>
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
@ -13,6 +14,7 @@ namespace PettingZoo.UI.Tab.Undocked
|
||||
private readonly ITabHostProvider tabHostProvider;
|
||||
private readonly ITab tab;
|
||||
private readonly DelegateCommand dockCommand;
|
||||
private bool docked;
|
||||
|
||||
|
||||
public string Title => tab.Title;
|
||||
@ -43,13 +45,18 @@ namespace PettingZoo.UI.Tab.Undocked
|
||||
|
||||
private void DockCommandExecute()
|
||||
{
|
||||
docked = true;
|
||||
tabHostProvider.Instance.DockTab(tab);
|
||||
}
|
||||
|
||||
|
||||
public void WindowClosed()
|
||||
{
|
||||
if (docked)
|
||||
return;
|
||||
|
||||
tabHostProvider.Instance.UndockedTabClosed(tab);
|
||||
(tab as IDisposable)?.Dispose();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace PettingZoo.UI.Tab.Undocked
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ using System.Windows.Controls;
|
||||
|
||||
namespace PettingZoo.UI.Tab
|
||||
{
|
||||
public class ViewTab<TView, TViewModel> : ITab, ITabToolbarCommands, ITabActivate, ITabHostWindowNotify where TView : ContentControl where TViewModel : INotifyPropertyChanged
|
||||
public class ViewTab<TView, TViewModel> : IDisposable, ITab, ITabToolbarCommands, ITabActivate, ITabHostWindowNotify where TView : ContentControl where TViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public string Title => getTitle(viewModel);
|
||||
public ContentControl Content { get; }
|
||||
@ -63,5 +63,12 @@ namespace PettingZoo.UI.Tab
|
||||
{
|
||||
(viewModel as ITabHostWindowNotify)?.HostWindowChanged(hostWindow);
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
(viewModel as IDisposable)?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
using PettingZoo.Core.Connection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PettingZoo.Core.Connection;
|
||||
using PettingZoo.Core.ExportImport;
|
||||
using PettingZoo.Core.Generator;
|
||||
using PettingZoo.UI.Tab.Publisher;
|
||||
@ -14,6 +16,10 @@ namespace PettingZoo.UI.Tab
|
||||
private readonly IExampleGenerator exampleGenerator;
|
||||
private readonly IExportImportFormatProvider exportImportFormatProvider;
|
||||
|
||||
// Not the cleanest way, but this factory itself can't be singleton without (justifyable) upsetting SimpleInjector
|
||||
private static ISubscriber? replySubscriber;
|
||||
private static ITab? replySubscriberTab;
|
||||
|
||||
|
||||
public ViewTabFactory(ILogger logger, ITabHostProvider tabHostProvider, IExampleGenerator exampleGenerator, IExportImportFormatProvider exportImportFormatProvider)
|
||||
{
|
||||
@ -24,23 +30,101 @@ namespace PettingZoo.UI.Tab
|
||||
}
|
||||
|
||||
|
||||
public ITab CreateSubscriberTab(IConnection? connection, ISubscriber subscriber)
|
||||
public void CreateSubscriberTab(IConnection? connection, ISubscriber subscriber)
|
||||
{
|
||||
var viewModel = new SubscriberViewModel(logger, tabHostProvider, this, connection, subscriber, exportImportFormatProvider);
|
||||
return new ViewTab<SubscriberView, SubscriberViewModel>(
|
||||
new SubscriberView(viewModel),
|
||||
viewModel,
|
||||
vm => vm.Title);
|
||||
InternalCreateSubscriberTab(connection, subscriber, false);
|
||||
}
|
||||
|
||||
|
||||
public ITab CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
|
||||
public string CreateReplySubscriberTab(IConnection connection)
|
||||
{
|
||||
var viewModel = new PublisherViewModel(tabHostProvider, this, connection, exampleGenerator, fromReceivedMessage);
|
||||
return new ViewTab<PublisherView, PublisherViewModel>(
|
||||
if (replySubscriber?.QueueName != null && replySubscriberTab != null)
|
||||
{
|
||||
tabHostProvider.Instance.ActivateTab(replySubscriberTab);
|
||||
return replySubscriber.QueueName;
|
||||
}
|
||||
|
||||
replySubscriber = new SubscriberDecorator(connection.Subscribe(), () =>
|
||||
{
|
||||
replySubscriber = null;
|
||||
replySubscriberTab = null;
|
||||
});
|
||||
|
||||
replySubscriber.Start();
|
||||
|
||||
replySubscriberTab = InternalCreateSubscriberTab(connection, replySubscriber, true);
|
||||
return replySubscriber.QueueName!;
|
||||
}
|
||||
|
||||
|
||||
public void CreatePublisherTab(IConnection connection, ReceivedMessageInfo? fromReceivedMessage = null)
|
||||
{
|
||||
var viewModel = new PublisherViewModel(this, connection, exampleGenerator, fromReceivedMessage);
|
||||
var tab = new ViewTab<PublisherView, PublisherViewModel>(
|
||||
new PublisherView(viewModel),
|
||||
viewModel,
|
||||
vm => vm.Title);
|
||||
|
||||
tabHostProvider.Instance.AddTab(tab);
|
||||
}
|
||||
|
||||
|
||||
private ITab InternalCreateSubscriberTab(IConnection? connection, ISubscriber subscriber, bool isReplyTab)
|
||||
{
|
||||
var viewModel = new SubscriberViewModel(logger, this, connection, subscriber, exportImportFormatProvider, isReplyTab);
|
||||
var tab = new ViewTab<SubscriberView, SubscriberViewModel>(
|
||||
new SubscriberView(viewModel),
|
||||
viewModel,
|
||||
vm => vm.Title);
|
||||
|
||||
tabHostProvider.Instance.AddTab(tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private class SubscriberDecorator : ISubscriber
|
||||
{
|
||||
private readonly ISubscriber decoratedSubscriber;
|
||||
private readonly Action onDispose;
|
||||
|
||||
|
||||
public string? QueueName => decoratedSubscriber.QueueName;
|
||||
public string? Exchange => decoratedSubscriber.Exchange;
|
||||
public string? RoutingKey => decoratedSubscriber.RoutingKey;
|
||||
|
||||
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||
|
||||
|
||||
public SubscriberDecorator(ISubscriber decoratedSubscriber, Action onDispose)
|
||||
{
|
||||
this.decoratedSubscriber = decoratedSubscriber;
|
||||
this.onDispose = onDispose;
|
||||
|
||||
decoratedSubscriber.MessageReceived += (sender, args) =>
|
||||
{
|
||||
MessageReceived?.Invoke(sender, args);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
decoratedSubscriber.Dispose();
|
||||
onDispose();
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<ReceivedMessageInfo> GetInitialMessages()
|
||||
{
|
||||
return decoratedSubscriber.GetInitialMessages();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
decoratedSubscriber.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user