Implemented raw publishing
This commit is contained in:
parent
503507422d
commit
229fc9415d
@ -8,7 +8,7 @@ namespace PettingZoo.Core.Connection
|
|||||||
event EventHandler<StatusChangedEventArgs> StatusChanged;
|
event EventHandler<StatusChangedEventArgs> StatusChanged;
|
||||||
|
|
||||||
ISubscriber Subscribe(string exchange, string routingKey);
|
ISubscriber Subscribe(string exchange, string routingKey);
|
||||||
Task Publish(MessageInfo messageInfo);
|
Task Publish(PublishMessageInfo messageInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,10 +15,10 @@ namespace PettingZoo.Core.Connection
|
|||||||
|
|
||||||
public class MessageReceivedEventArgs : EventArgs
|
public class MessageReceivedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public MessageInfo MessageInfo { get; }
|
public ReceivedMessageInfo MessageInfo { get; }
|
||||||
|
|
||||||
|
|
||||||
public MessageReceivedEventArgs(MessageInfo messageInfo)
|
public MessageReceivedEventArgs(ReceivedMessageInfo messageInfo)
|
||||||
{
|
{
|
||||||
MessageInfo = messageInfo;
|
MessageInfo = messageInfo;
|
||||||
}
|
}
|
||||||
|
@ -3,21 +3,72 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace PettingZoo.Core.Connection
|
namespace PettingZoo.Core.Connection
|
||||||
{
|
{
|
||||||
public class MessageInfo
|
public class BaseMessageInfo
|
||||||
{
|
{
|
||||||
public DateTime Timestamp { get; }
|
|
||||||
public string Exchange { get; }
|
public string Exchange { get; }
|
||||||
public string RoutingKey { get; }
|
public string RoutingKey { get; }
|
||||||
public byte[] Body { get; }
|
public byte[] Body { get; }
|
||||||
public IDictionary<string, string> Properties { get; }
|
public MessageProperties Properties { get; }
|
||||||
|
|
||||||
public MessageInfo(string exchange, string routingKey, byte[] body, IDictionary<string, string> properties, DateTime timestamp)
|
public BaseMessageInfo(string exchange, string routingKey, byte[] body, MessageProperties properties)
|
||||||
{
|
{
|
||||||
Exchange = exchange;
|
Exchange = exchange;
|
||||||
RoutingKey = routingKey;
|
RoutingKey = routingKey;
|
||||||
Body = body;
|
Body = body;
|
||||||
Properties = properties;
|
Properties = properties;
|
||||||
Timestamp = timestamp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ReceivedMessageInfo : BaseMessageInfo
|
||||||
|
{
|
||||||
|
public DateTime ReceivedTimestamp { get; }
|
||||||
|
|
||||||
|
public ReceivedMessageInfo(string exchange, string routingKey, byte[] body, MessageProperties properties, DateTime receivedTimestamp)
|
||||||
|
: base(exchange, routingKey, body, properties)
|
||||||
|
{
|
||||||
|
ReceivedTimestamp = receivedTimestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class PublishMessageInfo : BaseMessageInfo
|
||||||
|
{
|
||||||
|
public PublishMessageInfo(string exchange, string routingKey, byte[] body, MessageProperties properties)
|
||||||
|
: base(exchange, routingKey, body, properties)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public enum MessageDeliveryMode
|
||||||
|
{
|
||||||
|
NonPersistent = 1,
|
||||||
|
Persistent = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class MessageProperties
|
||||||
|
{
|
||||||
|
private static readonly IReadOnlyDictionary<string, string> EmptyHeaders = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public MessageProperties(IReadOnlyDictionary<string, string>? headers)
|
||||||
|
{
|
||||||
|
Headers = headers ?? EmptyHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? AppId { get; init; }
|
||||||
|
public string? ContentEncoding { get; init; }
|
||||||
|
public string? ContentType { get; init; }
|
||||||
|
public string? CorrelationId { get; init; }
|
||||||
|
public MessageDeliveryMode? DeliveryMode { get; init; }
|
||||||
|
public string? Expiration { get; init; }
|
||||||
|
public IReadOnlyDictionary<string, string> Headers { get; }
|
||||||
|
public string? MessageId { get; init; }
|
||||||
|
public byte? Priority { get; init; }
|
||||||
|
public string? ReplyTo { get; init; }
|
||||||
|
public DateTime? Timestamp { get; init; }
|
||||||
|
public string? Type { get; init; }
|
||||||
|
public string? UserId { get; init; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,19 @@
|
|||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Rendering\MessagePropertiesRendererStrings.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>MessagePropertiesRendererStrings.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Rendering\MessagePropertiesRendererStrings.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>MessagePropertiesRendererStrings.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -13,9 +13,9 @@ namespace PettingZoo.Core.Rendering
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public static string Render(byte[] body, string contentType = "")
|
public static string Render(byte[] body, string? contentType)
|
||||||
{
|
{
|
||||||
return ContentTypeHandlers.TryGetValue(contentType, out var handler)
|
return (contentType != null) && ContentTypeHandlers.TryGetValue(contentType, out var handler)
|
||||||
? handler(body)
|
? handler(body)
|
||||||
: Encoding.UTF8.GetString(body);
|
: Encoding.UTF8.GetString(body);
|
||||||
|
|
||||||
|
60
PettingZoo.Core/Rendering/MessagePropertiesRenderer.cs
Normal file
60
PettingZoo.Core/Rendering/MessagePropertiesRenderer.cs
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using PettingZoo.Core.Connection;
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Rendering
|
||||||
|
{
|
||||||
|
public class MessagePropertiesRenderer
|
||||||
|
{
|
||||||
|
public static IDictionary<string, string> Render(MessageProperties properties)
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
if (properties.AppId != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.AppId, properties.AppId);
|
||||||
|
|
||||||
|
if (properties.ContentEncoding != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.ContentEncoding, properties.ContentEncoding);
|
||||||
|
|
||||||
|
if (properties.ContentType != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.ContentType, properties.ContentType);
|
||||||
|
|
||||||
|
if (properties.CorrelationId != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.CorrelationId, properties.CorrelationId);
|
||||||
|
|
||||||
|
if (properties.DeliveryMode != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.DeliveryMode,
|
||||||
|
properties.DeliveryMode == MessageDeliveryMode.Persistent
|
||||||
|
? MessagePropertiesRendererStrings.DeliveryModePersistent
|
||||||
|
: MessagePropertiesRendererStrings.DeliveryModeNonPersistent);
|
||||||
|
|
||||||
|
if (properties.Expiration != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.Expiration, properties.Expiration);
|
||||||
|
|
||||||
|
if (properties.MessageId != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.MessageId, properties.MessageId);
|
||||||
|
|
||||||
|
if (properties.Priority != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.Priority, properties.Priority.Value.ToString());
|
||||||
|
|
||||||
|
if (properties.ReplyTo != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.ReplyTo, properties.ReplyTo);
|
||||||
|
|
||||||
|
if (properties.Timestamp != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.Timestamp, properties.Timestamp.Value.ToString("G"));
|
||||||
|
|
||||||
|
if (properties.Type != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.Type, properties.Type);
|
||||||
|
|
||||||
|
if (properties.UserId != null)
|
||||||
|
result.Add(MessagePropertiesRendererStrings.UserId, properties.UserId);
|
||||||
|
|
||||||
|
foreach (var (key, value) in properties.Headers)
|
||||||
|
{
|
||||||
|
if (!result.TryAdd(key, value))
|
||||||
|
result.TryAdd(MessagePropertiesRendererStrings.HeaderPrefix + key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
198
PettingZoo.Core/Rendering/MessagePropertiesRendererStrings.Designer.cs
generated
Normal file
198
PettingZoo.Core/Rendering/MessagePropertiesRendererStrings.Designer.cs
generated
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace PettingZoo.Core.Rendering {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class MessagePropertiesRendererStrings {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal MessagePropertiesRendererStrings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.Core.Rendering.MessagePropertiesRendererStrings", typeof(MessagePropertiesRendererStrings).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to App ID.
|
||||||
|
/// </summary>
|
||||||
|
internal static string AppId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AppId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Content encoding.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ContentEncoding {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContentEncoding", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Content type.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ContentType {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ContentType", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Correlation ID.
|
||||||
|
/// </summary>
|
||||||
|
internal static string CorrelationId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("CorrelationId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Delivery mode.
|
||||||
|
/// </summary>
|
||||||
|
internal static string DeliveryMode {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryMode", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Transient (1).
|
||||||
|
/// </summary>
|
||||||
|
internal static string DeliveryModeNonPersistent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryModeNonPersistent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Persistent (2).
|
||||||
|
/// </summary>
|
||||||
|
internal static string DeliveryModePersistent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryModePersistent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Expiration.
|
||||||
|
/// </summary>
|
||||||
|
internal static string Expiration {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Expiration", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Header: .
|
||||||
|
/// </summary>
|
||||||
|
internal static string HeaderPrefix {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("HeaderPrefix", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Message ID.
|
||||||
|
/// </summary>
|
||||||
|
internal static string MessageId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("MessageId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Priority.
|
||||||
|
/// </summary>
|
||||||
|
internal static string Priority {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Priority", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Reply To.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ReplyTo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ReplyTo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Timestamp.
|
||||||
|
/// </summary>
|
||||||
|
internal static string Timestamp {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Timestamp", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Type.
|
||||||
|
/// </summary>
|
||||||
|
internal static string Type {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Type", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to User ID.
|
||||||
|
/// </summary>
|
||||||
|
internal static string UserId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("UserId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
165
PettingZoo.Core/Rendering/MessagePropertiesRendererStrings.resx
Normal file
165
PettingZoo.Core/Rendering/MessagePropertiesRendererStrings.resx
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="AppId" xml:space="preserve">
|
||||||
|
<value>App ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContentEncoding" xml:space="preserve">
|
||||||
|
<value>Content encoding</value>
|
||||||
|
</data>
|
||||||
|
<data name="ContentType" xml:space="preserve">
|
||||||
|
<value>Content type</value>
|
||||||
|
</data>
|
||||||
|
<data name="CorrelationId" xml:space="preserve">
|
||||||
|
<value>Correlation ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeliveryMode" xml:space="preserve">
|
||||||
|
<value>Delivery mode</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeliveryModeNonPersistent" xml:space="preserve">
|
||||||
|
<value>Transient (1)</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeliveryModePersistent" xml:space="preserve">
|
||||||
|
<value>Persistent (2)</value>
|
||||||
|
</data>
|
||||||
|
<data name="Expiration" xml:space="preserve">
|
||||||
|
<value>Expiration</value>
|
||||||
|
</data>
|
||||||
|
<data name="HeaderPrefix" xml:space="preserve">
|
||||||
|
<value>Header: </value>
|
||||||
|
</data>
|
||||||
|
<data name="MessageId" xml:space="preserve">
|
||||||
|
<value>Message ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="Priority" xml:space="preserve">
|
||||||
|
<value>Priority</value>
|
||||||
|
</data>
|
||||||
|
<data name="ReplyTo" xml:space="preserve">
|
||||||
|
<value>Reply To</value>
|
||||||
|
</data>
|
||||||
|
<data name="Timestamp" xml:space="preserve">
|
||||||
|
<value>Timestamp</value>
|
||||||
|
</data>
|
||||||
|
<data name="Type" xml:space="preserve">
|
||||||
|
<value>Type</value>
|
||||||
|
</data>
|
||||||
|
<data name="UserId" xml:space="preserve">
|
||||||
|
<value>User ID</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
@ -81,7 +81,7 @@ namespace PettingZoo.RabbitMQ
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Task Publish(MessageInfo messageInfo)
|
public Task Publish(PublishMessageInfo messageInfo)
|
||||||
{
|
{
|
||||||
if (model == null)
|
if (model == null)
|
||||||
throw new InvalidOperationException("Not connected");
|
throw new InvalidOperationException("Not connected");
|
||||||
|
@ -1,136 +1,135 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
using System.Globalization;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using PettingZoo.Core.Connection;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
|
|
||||||
namespace PettingZoo.RabbitMQ
|
namespace PettingZoo.RabbitMQ
|
||||||
{
|
{
|
||||||
public static class RabbitMQClientPropertiesConverter
|
public static class RabbitMQClientPropertiesConverter
|
||||||
{
|
{
|
||||||
public static IDictionary<string, string> Convert(IBasicProperties basicProperties)
|
public static MessageProperties Convert(IBasicProperties basicProperties)
|
||||||
{
|
{
|
||||||
var properties = new Dictionary<string, string>();
|
return new MessageProperties(basicProperties.Headers?.ToDictionary(p => p.Key, p => Encoding.UTF8.GetString((byte[])p.Value)))
|
||||||
|
|
||||||
if (basicProperties.IsDeliveryModePresent())
|
|
||||||
properties.Add(RabbitMQProperties.DeliveryMode, basicProperties.DeliveryMode.ToString(CultureInfo.InvariantCulture));
|
|
||||||
|
|
||||||
if (basicProperties.IsContentTypePresent())
|
|
||||||
properties.Add(RabbitMQProperties.ContentType, basicProperties.ContentType);
|
|
||||||
|
|
||||||
if (basicProperties.IsContentEncodingPresent())
|
|
||||||
properties.Add(RabbitMQProperties.ContentEncoding, basicProperties.ContentEncoding);
|
|
||||||
|
|
||||||
if (basicProperties.IsPriorityPresent())
|
|
||||||
properties.Add(RabbitMQProperties.Priority, basicProperties.Priority.ToString(CultureInfo.InvariantCulture));
|
|
||||||
|
|
||||||
if (basicProperties.IsCorrelationIdPresent())
|
|
||||||
properties.Add(RabbitMQProperties.Priority, basicProperties.CorrelationId);
|
|
||||||
|
|
||||||
if (basicProperties.IsReplyToPresent())
|
|
||||||
properties.Add(RabbitMQProperties.ReplyTo, basicProperties.ReplyTo);
|
|
||||||
|
|
||||||
if (basicProperties.IsExpirationPresent())
|
|
||||||
properties.Add(RabbitMQProperties.Expiration, basicProperties.Expiration);
|
|
||||||
|
|
||||||
if (basicProperties.IsMessageIdPresent())
|
|
||||||
properties.Add(RabbitMQProperties.MessageId, basicProperties.MessageId);
|
|
||||||
|
|
||||||
if (basicProperties.IsTimestampPresent())
|
|
||||||
properties.Add(RabbitMQProperties.Timestamp, basicProperties.Timestamp.UnixTime.ToString(CultureInfo.InvariantCulture));
|
|
||||||
|
|
||||||
if (basicProperties.IsTypePresent())
|
|
||||||
properties.Add(RabbitMQProperties.Type, basicProperties.Type);
|
|
||||||
|
|
||||||
if (basicProperties.IsUserIdPresent())
|
|
||||||
properties.Add(RabbitMQProperties.UserId, basicProperties.UserId);
|
|
||||||
|
|
||||||
if (basicProperties.IsAppIdPresent())
|
|
||||||
properties.Add(RabbitMQProperties.UserId, basicProperties.AppId);
|
|
||||||
|
|
||||||
if (basicProperties.IsClusterIdPresent())
|
|
||||||
properties.Add(RabbitMQProperties.ClusterId, basicProperties.ClusterId);
|
|
||||||
|
|
||||||
// ReSharper disable once InvertIf
|
|
||||||
if (basicProperties.Headers != null)
|
|
||||||
{
|
{
|
||||||
foreach (var (key, value) in basicProperties.Headers)
|
DeliveryMode = basicProperties.IsDeliveryModePresent()
|
||||||
properties.Add(key, Encoding.UTF8.GetString((byte[]) value));
|
? basicProperties.DeliveryMode == 2 ? MessageDeliveryMode.Persistent :
|
||||||
}
|
MessageDeliveryMode.NonPersistent
|
||||||
|
: null,
|
||||||
|
|
||||||
return properties;
|
ContentType = basicProperties.IsContentTypePresent()
|
||||||
|
? basicProperties.ContentType
|
||||||
|
: null,
|
||||||
|
|
||||||
|
ContentEncoding = basicProperties.IsContentEncodingPresent()
|
||||||
|
? basicProperties.ContentEncoding
|
||||||
|
: null,
|
||||||
|
|
||||||
|
Priority = basicProperties.IsPriorityPresent()
|
||||||
|
? basicProperties.Priority
|
||||||
|
: null,
|
||||||
|
|
||||||
|
CorrelationId = basicProperties.IsCorrelationIdPresent()
|
||||||
|
? basicProperties.CorrelationId
|
||||||
|
: null,
|
||||||
|
|
||||||
|
ReplyTo = basicProperties.IsReplyToPresent()
|
||||||
|
? basicProperties.ReplyTo
|
||||||
|
: null,
|
||||||
|
|
||||||
|
Expiration = basicProperties.IsExpirationPresent()
|
||||||
|
? basicProperties.Expiration
|
||||||
|
: null,
|
||||||
|
|
||||||
|
MessageId = basicProperties.IsMessageIdPresent()
|
||||||
|
? basicProperties.MessageId
|
||||||
|
: null,
|
||||||
|
|
||||||
|
Timestamp = basicProperties.IsTimestampPresent()
|
||||||
|
? DateTimeOffset.FromUnixTimeMilliseconds(basicProperties.Timestamp.UnixTime).LocalDateTime
|
||||||
|
: null,
|
||||||
|
|
||||||
|
Type = basicProperties.IsTypePresent()
|
||||||
|
? basicProperties.Type
|
||||||
|
: null,
|
||||||
|
|
||||||
|
UserId = basicProperties.IsUserIdPresent()
|
||||||
|
? basicProperties.UserId
|
||||||
|
: null,
|
||||||
|
|
||||||
|
AppId = basicProperties.IsAppIdPresent()
|
||||||
|
? basicProperties.AppId
|
||||||
|
: null
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static IBasicProperties Convert(IDictionary<string, string> properties, IBasicProperties targetProperties)
|
public static IBasicProperties Convert(MessageProperties properties, IBasicProperties targetProperties)
|
||||||
{
|
{
|
||||||
foreach (var (key, value) in properties)
|
if (properties.DeliveryMode != null)
|
||||||
{
|
targetProperties.DeliveryMode = properties.DeliveryMode == MessageDeliveryMode.Persistent ? (byte)2 : (byte)1;
|
||||||
switch (key)
|
else
|
||||||
{
|
targetProperties.ClearDeliveryMode();
|
||||||
case RabbitMQProperties.DeliveryMode:
|
|
||||||
if (byte.TryParse(value, out var deliveryMode))
|
|
||||||
targetProperties.DeliveryMode = deliveryMode;
|
|
||||||
|
|
||||||
break;
|
if (properties.ContentType != null)
|
||||||
|
targetProperties.ContentType = properties.ContentType;
|
||||||
|
else
|
||||||
|
targetProperties.ClearContentType();
|
||||||
|
|
||||||
case RabbitMQProperties.ContentType:
|
if (properties.ContentEncoding != null)
|
||||||
targetProperties.ContentType = value;
|
targetProperties.ContentEncoding = properties.ContentEncoding;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearContentEncoding();
|
||||||
|
|
||||||
case RabbitMQProperties.ContentEncoding:
|
if (properties.Priority != null)
|
||||||
targetProperties.ContentEncoding = value;
|
targetProperties.Priority = properties.Priority.Value;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearPriority();
|
||||||
|
|
||||||
case RabbitMQProperties.Priority:
|
if (properties.CorrelationId != null)
|
||||||
if (byte.TryParse(value, out var priority))
|
targetProperties.CorrelationId = properties.CorrelationId;
|
||||||
targetProperties.Priority = priority;
|
else
|
||||||
|
targetProperties.ClearCorrelationId();
|
||||||
break;
|
|
||||||
|
|
||||||
case RabbitMQProperties.CorrelationId:
|
if (properties.ReplyTo != null)
|
||||||
targetProperties.CorrelationId = value;
|
targetProperties.ReplyTo = properties.ReplyTo;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearReplyTo();
|
||||||
case RabbitMQProperties.ReplyTo:
|
|
||||||
targetProperties.ReplyTo = value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RabbitMQProperties.Expiration:
|
if (properties.Expiration != null)
|
||||||
targetProperties.Expiration = value;
|
targetProperties.Expiration = properties.Expiration;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearExpiration();
|
||||||
|
|
||||||
case RabbitMQProperties.MessageId:
|
if (properties.MessageId != null)
|
||||||
targetProperties.MessageId = value;
|
targetProperties.MessageId = properties.MessageId;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearMessageId();
|
||||||
|
|
||||||
case RabbitMQProperties.Timestamp:
|
if (properties.Timestamp != null)
|
||||||
if (long.TryParse(value, out var timestamp))
|
targetProperties.Timestamp = new AmqpTimestamp(new DateTimeOffset(properties.Timestamp.Value).ToUnixTimeMilliseconds());
|
||||||
targetProperties.Timestamp = new AmqpTimestamp(timestamp);
|
else
|
||||||
|
targetProperties.ClearTimestamp();
|
||||||
break;
|
|
||||||
|
|
||||||
case RabbitMQProperties.Type:
|
if (properties.Type != null)
|
||||||
targetProperties.Type = value;
|
targetProperties.Type = properties.Type;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearType();
|
||||||
|
|
||||||
case RabbitMQProperties.UserId:
|
if (properties.UserId != null)
|
||||||
targetProperties.UserId = value;
|
targetProperties.UserId = properties.UserId;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearUserId();
|
||||||
|
|
||||||
case RabbitMQProperties.AppId:
|
if (properties.AppId != null)
|
||||||
targetProperties.AppId = value;
|
targetProperties.AppId = properties.AppId;
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearAppId();
|
||||||
|
|
||||||
case RabbitMQProperties.ClusterId:
|
if (properties.Headers.Count > 0)
|
||||||
targetProperties.ClusterId = value;
|
targetProperties.Headers = properties.Headers.ToDictionary(p => p.Key, p => (object)Encoding.UTF8.GetBytes(p.Value));
|
||||||
break;
|
else
|
||||||
|
targetProperties.ClearHeaders();
|
||||||
default:
|
|
||||||
targetProperties.Headers ??= new Dictionary<string, object>();
|
|
||||||
targetProperties.Headers.Add(key, Encoding.UTF8.GetBytes(value));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return targetProperties;
|
return targetProperties;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ namespace PettingZoo.RabbitMQ
|
|||||||
private void ClientReceived(object? sender, BasicDeliverEventArgs args)
|
private void ClientReceived(object? sender, BasicDeliverEventArgs args)
|
||||||
{
|
{
|
||||||
MessageReceived?.Invoke(this, new MessageReceivedEventArgs(
|
MessageReceived?.Invoke(this, new MessageReceivedEventArgs(
|
||||||
new MessageInfo(
|
new ReceivedMessageInfo(
|
||||||
args.Exchange,
|
args.Exchange,
|
||||||
args.RoutingKey,
|
args.RoutingKey,
|
||||||
args.Body.ToArray(),
|
args.Body.ToArray(),
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
namespace PettingZoo.RabbitMQ
|
|
||||||
{
|
|
||||||
public static class RabbitMQProperties
|
|
||||||
{
|
|
||||||
public const string ContentType = "content-type";
|
|
||||||
public const string ContentEncoding = "content-encoding";
|
|
||||||
public const string DeliveryMode = "delivery-mode";
|
|
||||||
public const string Priority = "priority";
|
|
||||||
public const string CorrelationId = "correlation-id";
|
|
||||||
public const string ReplyTo = "reply-to";
|
|
||||||
public const string Expiration = "expiration";
|
|
||||||
public const string MessageId = "message-id";
|
|
||||||
public const string Timestamp = "timestamp";
|
|
||||||
public const string Type = "type";
|
|
||||||
public const string UserId = "user-id";
|
|
||||||
public const string AppId = "app-id";
|
|
||||||
public const string ClusterId = "cluster-id";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PettingZoo.RabbitMQ
|
|
||||||
{
|
|
||||||
public static class RabbitMQPropertiesExtensions
|
|
||||||
{
|
|
||||||
public static string ContentType(this IDictionary<string, string> properties)
|
|
||||||
{
|
|
||||||
return properties.TryGetValue(RabbitMQProperties.ContentType, out var value)
|
|
||||||
? value
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -56,6 +56,11 @@
|
|||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="UI\Tab\Publisher\RawPublisherViewStrings.Designer.cs">
|
||||||
|
<DependentUpon>RawPublisherViewStrings.resx</DependentUpon>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
</Compile>
|
||||||
<Compile Update="UI\Tab\Publisher\PublisherViewStrings.Designer.cs">
|
<Compile Update="UI\Tab\Publisher\PublisherViewStrings.Designer.cs">
|
||||||
<DependentUpon>PublisherViewStrings.resx</DependentUpon>
|
<DependentUpon>PublisherViewStrings.resx</DependentUpon>
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
@ -81,6 +86,10 @@
|
|||||||
<LastGenOutput>SubscribeWindowStrings.Designer.cs</LastGenOutput>
|
<LastGenOutput>SubscribeWindowStrings.Designer.cs</LastGenOutput>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Update="UI\Tab\Publisher\RawPublisherViewStrings.resx">
|
||||||
|
<LastGenOutput>RawPublisherViewStrings.Designer.cs</LastGenOutput>
|
||||||
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Update="UI\Tab\Publisher\PublisherViewStrings.resx">
|
<EmbeddedResource Update="UI\Tab\Publisher\PublisherViewStrings.resx">
|
||||||
<LastGenOutput>PublisherViewStrings.Designer.cs</LastGenOutput>
|
<LastGenOutput>PublisherViewStrings.Designer.cs</LastGenOutput>
|
||||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||||
|
@ -12,7 +12,6 @@ using PettingZoo.UI.Connection;
|
|||||||
using PettingZoo.UI.Main;
|
using PettingZoo.UI.Main;
|
||||||
using PettingZoo.UI.Subscribe;
|
using PettingZoo.UI.Subscribe;
|
||||||
using PettingZoo.UI.Tab;
|
using PettingZoo.UI.Tab;
|
||||||
using PettingZoo.UI.Tab.Subscriber;
|
|
||||||
using SimpleInjector;
|
using SimpleInjector;
|
||||||
|
|
||||||
namespace PettingZoo
|
namespace PettingZoo
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
<Setter Property="Padding" Value="8,4"/>
|
<Setter Property="Padding" Value="8,4"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="{x:Type TextBox}">
|
||||||
|
<Setter Property="Padding" Value="3" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
<!-- Explicit styling -->
|
<!-- Explicit styling -->
|
||||||
<Style x:Key="SidePanel" TargetType="{x:Type Border}">
|
<Style x:Key="SidePanel" TargetType="{x:Type Border}">
|
||||||
<Setter Property="BorderThickness" Value="1"/>
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
@ -59,8 +64,17 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Key="RoutingKey">
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style x:Key="TypeSelection" TargetType="{x:Type FrameworkElement}">
|
<Style x:Key="TypeSelection" TargetType="{x:Type FrameworkElement}">
|
||||||
<Setter Property="Margin" Value="0 0 8 0" />
|
<Setter Property="Margin" Value="0 0 8 0" />
|
||||||
<Setter Property="VerticalAlignment" Value="Center" />
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
<Style x:Key="SectionLabel" TargetType="{x:Type Label}">
|
||||||
|
<Setter Property="FontWeight" Value="Bold"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
@ -9,7 +9,7 @@
|
|||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DataContext="{d:DesignInstance main:DesignTimeMainWindowViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance main:DesignTimeMainWindowViewModel, IsDesignTimeCreatable=True}"
|
||||||
Width="800"
|
Width="800"
|
||||||
Height="600"
|
Height="800"
|
||||||
ResizeMode="CanResizeWithGrip"
|
ResizeMode="CanResizeWithGrip"
|
||||||
Style="{StaticResource WindowStyle}"
|
Style="{StaticResource WindowStyle}"
|
||||||
Title="{x:Static main:MainWindowStrings.WindowTitle}"
|
Title="{x:Static main:MainWindowStrings.WindowTitle}"
|
||||||
|
@ -37,7 +37,8 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
|
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
viewModel.ConnectCommand.Execute(null);
|
// TODO support command-line parameters for easier testing
|
||||||
|
//viewModel.ConnectCommand.Execute(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,8 +93,11 @@ namespace PettingZoo.UI.Main
|
|||||||
|
|
||||||
private async void ConnectExecute()
|
private async void ConnectExecute()
|
||||||
{
|
{
|
||||||
//var newParams = connectionDialog.Show(connectionDialogParams);
|
var newParams = connectionDialog.Show(connectionDialogParams);
|
||||||
var newParams = new ConnectionDialogParams("localhost", "/", 5672, "guest", "guest", true, "lef", "#");
|
|
||||||
|
// TODO support command-line parameters for easier testing
|
||||||
|
// var newParams = new ConnectionDialogParams("localhost", "/", 5672, "guest", "guest", true, "test", "#");
|
||||||
|
|
||||||
if (newParams == null)
|
if (newParams == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -9,13 +9,20 @@
|
|||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
d:DataContext="{d:DesignInstance res:DesignTimePublisherViewModel, IsDesignTimeCreatable=True}"
|
||||||
Background="White">
|
Background="White">
|
||||||
<StackPanel Margin="4">
|
<Grid Margin="4">
|
||||||
<StackPanel Orientation="Horizontal">
|
<Grid.RowDefinitions>
|
||||||
<TextBlock Text="{x:Static res:PublisherViewStrings.LabelMessageType}" Style="{StaticResource TypeSelection}" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Grid.Row="0">
|
||||||
|
<Label Content="{x:Static res:PublisherViewStrings.LabelMessageType}" Style="{StaticResource TypeSelection}" />
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeRaw}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeRaw}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeRaw}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeRaw}" />
|
||||||
<RadioButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeTapeti}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeTapeti}" />
|
<RadioButton Content="{x:Static res:PublisherViewStrings.OptionMessageTypeTapeti}" Style="{StaticResource TypeSelection}" IsChecked="{Binding MessageTypeTapeti}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<TextBlock>TODO: implement publish forms</TextBlock>
|
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
||||||
</StackPanel>
|
<ContentControl Margin="0 8 0 0" Content="{Binding MessageTypeControl}" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
|
|
||||||
@ -16,6 +18,11 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
private readonly IConnection connection;
|
private readonly IConnection connection;
|
||||||
|
|
||||||
private MessageType messageType;
|
private MessageType messageType;
|
||||||
|
private UserControl? messageTypeControl;
|
||||||
|
private ICommand? messageTypePublishCommand;
|
||||||
|
|
||||||
|
private UserControl? rawPublisherView;
|
||||||
|
private UserControl? tapetiPublisherView;
|
||||||
|
|
||||||
private readonly DelegateCommand publishCommand;
|
private readonly DelegateCommand publishCommand;
|
||||||
private readonly TabToolbarCommand[] toolbarCommands;
|
private readonly TabToolbarCommand[] toolbarCommands;
|
||||||
@ -24,15 +31,20 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
public MessageType MessageType
|
public MessageType MessageType
|
||||||
{
|
{
|
||||||
get => messageType;
|
get => messageType;
|
||||||
set => SetField(ref messageType, value,
|
set
|
||||||
otherPropertiesChanged: new[]
|
{
|
||||||
|
if (SetField(ref messageType, value,
|
||||||
|
otherPropertiesChanged: new[]
|
||||||
|
{
|
||||||
|
nameof(MessageTypeRaw),
|
||||||
|
nameof(MessageTypeTapeti)
|
||||||
|
}))
|
||||||
{
|
{
|
||||||
nameof(MessageTypeRaw),
|
SetMessageTypeControl(value);
|
||||||
nameof(MessageTypeTapeti)
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool MessageTypeRaw
|
public bool MessageTypeRaw
|
||||||
{
|
{
|
||||||
get => MessageType == MessageType.Raw;
|
get => MessageType == MessageType.Raw;
|
||||||
@ -46,6 +58,13 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UserControl? MessageTypeControl
|
||||||
|
{
|
||||||
|
get => messageTypeControl;
|
||||||
|
set => SetField(ref messageTypeControl, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ICommand PublishCommand => publishCommand;
|
public ICommand PublishCommand => publishCommand;
|
||||||
|
|
||||||
|
|
||||||
@ -64,19 +83,49 @@ namespace PettingZoo.UI.Tab.Publisher
|
|||||||
{
|
{
|
||||||
new TabToolbarCommand(PublishCommand, PublisherViewStrings.CommandPublish, SvgIconHelper.LoadFromResource("/Images/PublishSend.svg"))
|
new TabToolbarCommand(PublishCommand, PublisherViewStrings.CommandPublish, SvgIconHelper.LoadFromResource("/Images/PublishSend.svg"))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SetMessageTypeControl(MessageType.Raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void PublishExecute()
|
private void PublishExecute()
|
||||||
{
|
{
|
||||||
// TODO
|
messageTypePublishCommand?.Execute(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool PublishCanExecute()
|
private bool PublishCanExecute()
|
||||||
{
|
{
|
||||||
// TODO validate input
|
return messageTypePublishCommand?.CanExecute(null) ?? false;
|
||||||
return true;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SetMessageTypeControl(MessageType value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case MessageType.Raw:
|
||||||
|
var rawPublisherViewModel = new RawPublisherViewModel(connection);
|
||||||
|
rawPublisherView ??= new RawPublisherView(rawPublisherViewModel);
|
||||||
|
MessageTypeControl = rawPublisherView;
|
||||||
|
|
||||||
|
messageTypePublishCommand = rawPublisherViewModel.PublishCommand;
|
||||||
|
publishCommand.RaiseCanExecuteChanged();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageType.Tapeti:
|
||||||
|
// TODO
|
||||||
|
var tapetiPublisherViewModel = new RawPublisherViewModel(connection);
|
||||||
|
tapetiPublisherView ??= new RawPublisherView(tapetiPublisherViewModel);
|
||||||
|
MessageTypeControl = tapetiPublisherView;
|
||||||
|
|
||||||
|
messageTypePublishCommand = tapetiPublisherViewModel.PublishCommand;
|
||||||
|
publishCommand.RaiseCanExecuteChanged();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
166
PettingZoo/UI/Tab/Publisher/RawPublisherView.xaml
Normal file
166
PettingZoo/UI/Tab/Publisher/RawPublisherView.xaml
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<UserControl x:Class="PettingZoo.UI.Tab.Publisher.RawPublisherView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:publisher="clr-namespace:PettingZoo.UI.Tab.Publisher"
|
||||||
|
xmlns:ui="clr-namespace:PettingZoo.UI"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="800" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance publisher:DesignTimeRawPublisherViewModel, IsDesignTimeCreatable=True}"
|
||||||
|
Background="White">
|
||||||
|
<ui:GridLayout Style="{StaticResource Form}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<ui:GridLayout.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="16"/>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="16"/>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</ui:GridLayout.RowDefinitions>
|
||||||
|
|
||||||
|
|
||||||
|
<Label Grid.Row="0" Grid.Column="1">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<RadioButton Content="{x:Static publisher:RawPublisherViewStrings.LabelSendToExchange}" IsChecked="{Binding SendToExchange}" Style="{StaticResource TypeSelection}" />
|
||||||
|
<RadioButton Content="{x:Static publisher:RawPublisherViewStrings.LabelSendToQueue}" IsChecked="{Binding SendToQueue}" Style="{StaticResource TypeSelection}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Label Grid.Row="1" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelExchange}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Exchange}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="2" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelRoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding RoutingKey}" Visibility="{Binding ExchangeVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="3" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelQueue}" Visibility="{Binding QueueVisibility}" />
|
||||||
|
<TextBox Grid.Row="3" Grid.Column="1" Text="{Binding Queue}" Visibility="{Binding QueueVisibility}" />
|
||||||
|
|
||||||
|
|
||||||
|
<Label Grid.Row="5" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelDeliveryMode}" />
|
||||||
|
<ComboBox Grid.Row="5" Grid.Column="1" SelectedIndex="{Binding DeliveryModeIndex}">
|
||||||
|
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModeNonPersistent}" />
|
||||||
|
<ComboBoxItem Content="{x:Static publisher:RawPublisherViewStrings.DeliveryModePersistent}" />
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<Label Grid.Row="6" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelHeaders}" />
|
||||||
|
<ItemsControl Grid.Row="6" Grid.Column="1" ItemsSource="{Binding Headers}">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Vertical" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Margin="0 0 0 8">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Grid Grid.Column="0" >
|
||||||
|
<TextBox Text="{Binding Key, UpdateSourceTrigger=PropertyChanged}" LostFocus="Header_OnLostFocus" Margin="0 0 8 0" x:Name="HeaderKey" />
|
||||||
|
<TextBlock IsHitTestVisible="False" Text="{x:Static publisher:RawPublisherViewStrings.HeaderName}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="{x:Type TextBlock}">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Text, ElementName=HeaderKey}" Value="">
|
||||||
|
<Setter Property="Visibility" Value="Visible"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Column="1">
|
||||||
|
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}" LostFocus="Header_OnLostFocus" x:Name="HeaderValue" />
|
||||||
|
<TextBlock IsHitTestVisible="False" Text="{x:Static publisher:RawPublisherViewStrings.HeaderValue}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="{x:Type TextBlock}">
|
||||||
|
<Setter Property="Visibility" Value="Collapsed"/>
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Text, ElementName=HeaderValue}" Value="">
|
||||||
|
<Setter Property="Visibility" Value="Visible"/>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
|
<Label Grid.Row="7" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelProperties}" Style="{StaticResource SectionLabel}"/>
|
||||||
|
|
||||||
|
<Label Grid.Row="8" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentType}" />
|
||||||
|
<TextBox Grid.Row="8" Grid.Column="1" Text="{Binding ContentType}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="9" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelCorrelationId}" />
|
||||||
|
<TextBox Grid.Row="9" Grid.Column="1" Text="{Binding CorrelationId}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="10" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelReplyTo}" />
|
||||||
|
<TextBox Grid.Row="10" Grid.Column="1" Text="{Binding ReplyTo}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="11" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelAppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="11" Grid.Column="1" Text="{Binding AppId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="12" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelContentEncoding}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="12" Grid.Column="1" Text="{Binding ContentEncoding}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="13" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelExpiration}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="13" Grid.Column="1" Text="{Binding Expiration}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="14" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelMessageId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="14" Grid.Column="1" Text="{Binding MessageId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="15" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPriority}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="15" Grid.Column="1" Text="{Binding Priority}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="16" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelTimestamp}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="16" Grid.Column="1" Text="{Binding Timestamp}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="17" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelType}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="17" Grid.Column="1" Text="{Binding TypeProperty}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
<Label Grid.Row="18" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelUserId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
<TextBox Grid.Row="18" Grid.Column="1" Text="{Binding UserId}" Visibility="{Binding PropertiesExpandedVisibility}" />
|
||||||
|
|
||||||
|
|
||||||
|
<Button Grid.Row="19" Grid.Column="1" Content="{Binding PropertiesExpandedCollapsedText}" Command="{Binding PropertiesExpandCollapseCommand}" Cursor="Hand">
|
||||||
|
<Button.Template>
|
||||||
|
<ControlTemplate TargetType="{x:Type Button}">
|
||||||
|
<ContentPresenter />
|
||||||
|
</ControlTemplate>
|
||||||
|
</Button.Template>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Label Grid.Row="21" Grid.Column="0" Content="{x:Static publisher:RawPublisherViewStrings.LabelPayload}" />
|
||||||
|
<TextBox Grid.Row="21" Grid.Column="1" Text="{Binding Payload}" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Height="150" />
|
||||||
|
</ui:GridLayout>
|
||||||
|
</UserControl>
|
67
PettingZoo/UI/Tab/Publisher/RawPublisherView.xaml.cs
Normal file
67
PettingZoo/UI/Tab/Publisher/RawPublisherView.xaml.cs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for RawPublisherView.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class RawPublisherView
|
||||||
|
{
|
||||||
|
private RawPublisherViewModel viewModel;
|
||||||
|
private DispatcherTimer checkEmptyHeaderTimer;
|
||||||
|
|
||||||
|
|
||||||
|
public RawPublisherView(RawPublisherViewModel viewModel)
|
||||||
|
{
|
||||||
|
this.viewModel = viewModel;
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = viewModel;
|
||||||
|
|
||||||
|
checkEmptyHeaderTimer = new DispatcherTimer();
|
||||||
|
checkEmptyHeaderTimer.Tick += CheckEmptyHeaderTimerOnTick;
|
||||||
|
checkEmptyHeaderTimer.Interval = TimeSpan.FromMilliseconds(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Header_OnLostFocus(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var dataContext = (sender as FrameworkElement)?.DataContext;
|
||||||
|
if (dataContext is not RawPublisherViewModel.Header header)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!header.IsEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// At this point the focused element is null, so we need to check again in a bit. This will prevent
|
||||||
|
// the header line from being removed when jumping between empty key and value textboxes
|
||||||
|
checkEmptyHeaderTimer.Stop();
|
||||||
|
checkEmptyHeaderTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void CheckEmptyHeaderTimerOnTick(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
checkEmptyHeaderTimer.Stop();
|
||||||
|
|
||||||
|
RawPublisherViewModel.Header? focusedHeader = null;
|
||||||
|
|
||||||
|
var focusedControl = Keyboard.FocusedElement;
|
||||||
|
if (focusedControl is FrameworkElement { DataContext: RawPublisherViewModel.Header header })
|
||||||
|
focusedHeader = header;
|
||||||
|
|
||||||
|
var emptyheaders = viewModel.Headers
|
||||||
|
.Take(viewModel.Headers.Count - 1)
|
||||||
|
.Where(h => h != focusedHeader && h.IsEmpty())
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
foreach (var emptyHeader in emptyheaders)
|
||||||
|
viewModel.Headers.Remove(emptyHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
322
PettingZoo/UI/Tab/Publisher/RawPublisherViewModel.cs
Normal file
322
PettingZoo/UI/Tab/Publisher/RawPublisherViewModel.cs
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using PettingZoo.Core.Connection;
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Tab.Publisher
|
||||||
|
{
|
||||||
|
public class RawPublisherViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly IConnection connection;
|
||||||
|
private readonly DelegateCommand publishCommand;
|
||||||
|
private readonly DelegateCommand propertiesExpandCollapseCommand;
|
||||||
|
private bool propertiesExpanded;
|
||||||
|
|
||||||
|
private bool sendToExchange = true;
|
||||||
|
private string exchange = "";
|
||||||
|
private string routingKey = "";
|
||||||
|
private string queue = "";
|
||||||
|
|
||||||
|
private MessageDeliveryMode deliveryMode;
|
||||||
|
|
||||||
|
private string contentType = "application/json";
|
||||||
|
private string correlationId = "";
|
||||||
|
private string replyTo = "";
|
||||||
|
private string appId = "";
|
||||||
|
private string contentEncoding = "";
|
||||||
|
private string expiration = "";
|
||||||
|
private string messageId = "";
|
||||||
|
private string priority = "";
|
||||||
|
private string timestamp = "";
|
||||||
|
private string typeProperty = "";
|
||||||
|
private string userId = "";
|
||||||
|
private string payload = "";
|
||||||
|
|
||||||
|
|
||||||
|
public bool SendToExchange
|
||||||
|
{
|
||||||
|
get => sendToExchange;
|
||||||
|
set => SetField(ref sendToExchange, value, otherPropertiesChanged: new[] { nameof(SendToQueue), nameof(ExchangeVisibility), nameof(QueueVisibility) });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool SendToQueue
|
||||||
|
{
|
||||||
|
get => !SendToExchange;
|
||||||
|
set => SendToExchange = !value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Exchange
|
||||||
|
{
|
||||||
|
get => exchange;
|
||||||
|
set => SetField(ref exchange, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string RoutingKey
|
||||||
|
{
|
||||||
|
get => routingKey;
|
||||||
|
set => SetField(ref routingKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Queue
|
||||||
|
{
|
||||||
|
get => queue;
|
||||||
|
set => SetField(ref queue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public virtual Visibility ExchangeVisibility => SendToExchange ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
public virtual Visibility QueueVisibility => SendToQueue ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
|
||||||
|
|
||||||
|
public int DeliveryModeIndex
|
||||||
|
{
|
||||||
|
get => deliveryMode == MessageDeliveryMode.Persistent ? 1 : 0;
|
||||||
|
set => SetField(ref deliveryMode, value == 1 ? MessageDeliveryMode.Persistent : MessageDeliveryMode.NonPersistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ContentType
|
||||||
|
{
|
||||||
|
get => contentType;
|
||||||
|
set => SetField(ref contentType, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string CorrelationId
|
||||||
|
{
|
||||||
|
get => correlationId;
|
||||||
|
set => SetField(ref correlationId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ReplyTo
|
||||||
|
{
|
||||||
|
get => replyTo;
|
||||||
|
set => SetField(ref replyTo, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string AppId
|
||||||
|
{
|
||||||
|
get => appId;
|
||||||
|
set => SetField(ref appId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string ContentEncoding
|
||||||
|
{
|
||||||
|
get => contentEncoding;
|
||||||
|
set => SetField(ref contentEncoding, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Expiration
|
||||||
|
{
|
||||||
|
get => expiration;
|
||||||
|
set => SetField(ref expiration, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string MessageId
|
||||||
|
{
|
||||||
|
get => messageId;
|
||||||
|
set => SetField(ref messageId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Priority
|
||||||
|
{
|
||||||
|
get => priority;
|
||||||
|
set => SetField(ref priority, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Timestamp
|
||||||
|
{
|
||||||
|
get => timestamp;
|
||||||
|
set => SetField(ref timestamp, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string TypeProperty
|
||||||
|
{
|
||||||
|
get => typeProperty;
|
||||||
|
set => SetField(ref typeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string UserId
|
||||||
|
{
|
||||||
|
get => userId;
|
||||||
|
set => SetField(ref userId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Payload
|
||||||
|
{
|
||||||
|
get => payload;
|
||||||
|
set => SetField(ref payload, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ObservableCollection<Header> Headers { get; } = new();
|
||||||
|
|
||||||
|
|
||||||
|
public ICommand PublishCommand => publishCommand;
|
||||||
|
public ICommand PropertiesExpandCollapseCommand => propertiesExpandCollapseCommand;
|
||||||
|
|
||||||
|
|
||||||
|
public bool PropertiesExpanded
|
||||||
|
{
|
||||||
|
get => propertiesExpanded;
|
||||||
|
set => SetField(ref propertiesExpanded, value, otherPropertiesChanged: new[]
|
||||||
|
{
|
||||||
|
nameof(PropertiesExpandedVisibility),
|
||||||
|
nameof(PropertiesExpandedCollapsedText)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public Visibility PropertiesExpandedVisibility => propertiesExpanded ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
public string PropertiesExpandedCollapsedText => propertiesExpanded
|
||||||
|
? RawPublisherViewStrings.PropertiesCollapse
|
||||||
|
: RawPublisherViewStrings.PropertiesExpand;
|
||||||
|
|
||||||
|
|
||||||
|
protected Header lastHeader;
|
||||||
|
|
||||||
|
|
||||||
|
public RawPublisherViewModel(IConnection connection)
|
||||||
|
{
|
||||||
|
this.connection = connection;
|
||||||
|
|
||||||
|
publishCommand = new DelegateCommand(PublishExecute, PublishCanExecute);
|
||||||
|
propertiesExpandCollapseCommand = new DelegateCommand(PropertiesExpandCollapseExecute);
|
||||||
|
|
||||||
|
AddHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void LastHeaderChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
lastHeader.PropertyChanged -= LastHeaderChanged;
|
||||||
|
AddHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MemberNotNull(nameof(lastHeader))]
|
||||||
|
private void AddHeader()
|
||||||
|
{
|
||||||
|
lastHeader = new Header();
|
||||||
|
lastHeader.PropertyChanged += LastHeaderChanged;
|
||||||
|
Headers.Add(lastHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void PropertiesExpandCollapseExecute()
|
||||||
|
{
|
||||||
|
PropertiesExpanded = !PropertiesExpanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void PublishExecute()
|
||||||
|
{
|
||||||
|
static string? NullIfEmpty(string? value)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(value) ? null : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO check parsing of priority and timestamp
|
||||||
|
// TODO support for Reply To to dynamic queue which waits for a message (or opens a new subscriber tab?)
|
||||||
|
|
||||||
|
var headers = Headers.Where(h => h.IsValid()).ToDictionary(h => h.Key, h => h.Value);
|
||||||
|
|
||||||
|
// TODO background worker / async
|
||||||
|
|
||||||
|
connection.Publish(new PublishMessageInfo(
|
||||||
|
SendToExchange ? Exchange : "",
|
||||||
|
SendToExchange ? RoutingKey : Queue,
|
||||||
|
Encoding.UTF8.GetBytes(Payload),
|
||||||
|
new MessageProperties(headers)
|
||||||
|
{
|
||||||
|
AppId = NullIfEmpty(AppId),
|
||||||
|
ContentEncoding = NullIfEmpty(ContentEncoding),
|
||||||
|
ContentType = NullIfEmpty(ContentType),
|
||||||
|
CorrelationId = NullIfEmpty(CorrelationId),
|
||||||
|
DeliveryMode = deliveryMode,
|
||||||
|
Expiration = NullIfEmpty(Expiration),
|
||||||
|
MessageId = NullIfEmpty(MessageId),
|
||||||
|
Priority = !string.IsNullOrEmpty(Priority) && byte.TryParse(Priority, out var priorityValue) ? priorityValue : null,
|
||||||
|
ReplyTo = NullIfEmpty(ReplyTo),
|
||||||
|
Timestamp = !string.IsNullOrEmpty(Timestamp) && DateTime.TryParse(Timestamp, out var timestampValue) ? timestampValue : null,
|
||||||
|
Type = NullIfEmpty(TypeProperty),
|
||||||
|
UserId = NullIfEmpty(UserId)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool PublishCanExecute()
|
||||||
|
{
|
||||||
|
// TODO validate input
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class Header : BaseViewModel
|
||||||
|
{
|
||||||
|
private string key = "";
|
||||||
|
private string value = "";
|
||||||
|
|
||||||
|
|
||||||
|
public string Key
|
||||||
|
{
|
||||||
|
get => key;
|
||||||
|
set => SetField(ref key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string Value
|
||||||
|
{
|
||||||
|
get => value;
|
||||||
|
set => SetField(ref this.value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsEmpty()
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(Key) && string.IsNullOrEmpty(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsValid()
|
||||||
|
{
|
||||||
|
return !string.IsNullOrEmpty(Key) && !string.IsNullOrEmpty(Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class DesignTimeRawPublisherViewModel : RawPublisherViewModel
|
||||||
|
{
|
||||||
|
public DesignTimeRawPublisherViewModel() : base(null!)
|
||||||
|
{
|
||||||
|
PropertiesExpanded = true;
|
||||||
|
|
||||||
|
var capturedLastHeader = lastHeader;
|
||||||
|
capturedLastHeader.Key = "Example";
|
||||||
|
capturedLastHeader.Value = "header";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override Visibility ExchangeVisibility => Visibility.Visible;
|
||||||
|
public override Visibility QueueVisibility => Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
297
PettingZoo/UI/Tab/Publisher/RawPublisherViewStrings.Designer.cs
generated
Normal file
297
PettingZoo/UI/Tab/Publisher/RawPublisherViewStrings.Designer.cs
generated
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace PettingZoo.UI.Tab.Publisher {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
public class RawPublisherViewStrings {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal RawPublisherViewStrings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
public static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PettingZoo.UI.Tab.Publisher.RawPublisherViewStrings", typeof(RawPublisherViewStrings).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
public static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Transient (non-persistent).
|
||||||
|
/// </summary>
|
||||||
|
public static string DeliveryModeNonPersistent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryModeNonPersistent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Persistent.
|
||||||
|
/// </summary>
|
||||||
|
public static string DeliveryModePersistent {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DeliveryModePersistent", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Name.
|
||||||
|
/// </summary>
|
||||||
|
public static string HeaderName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("HeaderName", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Value.
|
||||||
|
/// </summary>
|
||||||
|
public static string HeaderValue {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("HeaderValue", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to App ID.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelAppId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelAppId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Content encoding.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelContentEncoding {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelContentEncoding", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Content type.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelContentType {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelContentType", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Correlation ID.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelCorrelationId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelCorrelationId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Delivery mode.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelDeliveryMode {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelDeliveryMode", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Exchange.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelExchange {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelExchange", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Expiration.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelExpiration {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelExpiration", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Headers.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelHeaders {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelHeaders", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Message ID.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelMessageId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelMessageId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Payload.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelPayload {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelPayload", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Priority.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelPriority {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelPriority", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Properties.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelProperties {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelProperties", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Queue.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelQueue {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelQueue", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Reply To.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelReplyTo {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelReplyTo", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Routing key.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelRoutingKey {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelRoutingKey", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Publish to exchange (topic).
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelSendToExchange {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelSendToExchange", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Publish to queue (direct).
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelSendToQueue {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelSendToQueue", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Timestamp.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelTimestamp {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelTimestamp", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Type.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelType {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelType", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to User ID.
|
||||||
|
/// </summary>
|
||||||
|
public static string LabelUserId {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("LabelUserId", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to ⏶ Collapse.
|
||||||
|
/// </summary>
|
||||||
|
public static string PropertiesCollapse {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PropertiesCollapse", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to ⏷ Expand.
|
||||||
|
/// </summary>
|
||||||
|
public static string PropertiesExpand {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("PropertiesExpand", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
198
PettingZoo/UI/Tab/Publisher/RawPublisherViewStrings.resx
Normal file
198
PettingZoo/UI/Tab/Publisher/RawPublisherViewStrings.resx
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<data name="DeliveryModeNonPersistent" xml:space="preserve">
|
||||||
|
<value>Transient (non-persistent)</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeliveryModePersistent" xml:space="preserve">
|
||||||
|
<value>Persistent</value>
|
||||||
|
</data>
|
||||||
|
<data name="HeaderName" xml:space="preserve">
|
||||||
|
<value>Name</value>
|
||||||
|
</data>
|
||||||
|
<data name="HeaderValue" xml:space="preserve">
|
||||||
|
<value>Value</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelAppId" xml:space="preserve">
|
||||||
|
<value>App ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelContentEncoding" xml:space="preserve">
|
||||||
|
<value>Content encoding</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelContentType" xml:space="preserve">
|
||||||
|
<value>Content type</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelCorrelationId" xml:space="preserve">
|
||||||
|
<value>Correlation ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelDeliveryMode" xml:space="preserve">
|
||||||
|
<value>Delivery mode</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelExchange" xml:space="preserve">
|
||||||
|
<value>Exchange</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelExpiration" xml:space="preserve">
|
||||||
|
<value>Expiration</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelHeaders" xml:space="preserve">
|
||||||
|
<value>Headers</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelMessageId" xml:space="preserve">
|
||||||
|
<value>Message ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelPayload" xml:space="preserve">
|
||||||
|
<value>Payload</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelPriority" xml:space="preserve">
|
||||||
|
<value>Priority</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelProperties" xml:space="preserve">
|
||||||
|
<value>Properties</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelQueue" xml:space="preserve">
|
||||||
|
<value>Queue</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelReplyTo" xml:space="preserve">
|
||||||
|
<value>Reply To</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelRoutingKey" xml:space="preserve">
|
||||||
|
<value>Routing key</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelSendToExchange" xml:space="preserve">
|
||||||
|
<value>Publish to exchange (topic)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelSendToQueue" xml:space="preserve">
|
||||||
|
<value>Publish to queue (direct)</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelTimestamp" xml:space="preserve">
|
||||||
|
<value>Timestamp</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelType" xml:space="preserve">
|
||||||
|
<value>Type</value>
|
||||||
|
</data>
|
||||||
|
<data name="LabelUserId" xml:space="preserve">
|
||||||
|
<value>User ID</value>
|
||||||
|
</data>
|
||||||
|
<data name="PropertiesCollapse" xml:space="preserve">
|
||||||
|
<value>⏶ Collapse</value>
|
||||||
|
</data>
|
||||||
|
<data name="PropertiesExpand" xml:space="preserve">
|
||||||
|
<value>⏷ Expand</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
@ -28,8 +28,8 @@
|
|||||||
<ColumnDefinition Width="Auto" MinWidth="150"/>
|
<ColumnDefinition Width="Auto" MinWidth="150"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding Timestamp, StringFormat=g}" Style="{StaticResource Timestamp}"></TextBlock>
|
<TextBlock Grid.Column="0" Grid.Row="0" Text="{Binding ReceivedTimestamp, StringFormat=g}" Style="{StaticResource Timestamp}"></TextBlock>
|
||||||
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding RoutingKey}" Style="{StaticResource Routingkey}"></TextBlock>
|
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding RoutingKey}" Style="{StaticResource RoutingKey}"></TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
|
@ -6,7 +6,6 @@ using System.Threading.Tasks;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using PettingZoo.Core.Connection;
|
using PettingZoo.Core.Connection;
|
||||||
using PettingZoo.Core.Rendering;
|
using PettingZoo.Core.Rendering;
|
||||||
using PettingZoo.RabbitMQ;
|
|
||||||
|
|
||||||
// TODO update title with unread message count if tab is not active
|
// TODO update title with unread message count if tab is not active
|
||||||
|
|
||||||
@ -16,36 +15,36 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
{
|
{
|
||||||
private readonly ISubscriber subscriber;
|
private readonly ISubscriber subscriber;
|
||||||
private readonly TaskScheduler uiScheduler;
|
private readonly TaskScheduler uiScheduler;
|
||||||
private MessageInfo? selectedMessage;
|
private ReceivedMessageInfo? selectedMessage;
|
||||||
private readonly DelegateCommand clearCommand;
|
private readonly DelegateCommand clearCommand;
|
||||||
private readonly TabToolbarCommand[] toolbarCommands;
|
private readonly TabToolbarCommand[] toolbarCommands;
|
||||||
|
private IDictionary<string, string>? selectedMessageProperties;
|
||||||
|
|
||||||
|
|
||||||
public ICommand ClearCommand => clearCommand;
|
public ICommand ClearCommand => clearCommand;
|
||||||
|
|
||||||
public ObservableCollection<MessageInfo> Messages { get; }
|
public ObservableCollection<ReceivedMessageInfo> Messages { get; }
|
||||||
|
|
||||||
public MessageInfo? SelectedMessage
|
public ReceivedMessageInfo? SelectedMessage
|
||||||
{
|
{
|
||||||
get => selectedMessage;
|
get => selectedMessage;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value == selectedMessage)
|
if (SetField(ref selectedMessage, value, otherPropertiesChanged: new[] { nameof(SelectedMessageBody) }))
|
||||||
return;
|
UpdateSelectedMessageProperties();
|
||||||
|
|
||||||
selectedMessage = value;
|
|
||||||
RaisePropertyChanged();
|
|
||||||
RaiseOtherPropertyChanged(nameof(SelectedMessageBody));
|
|
||||||
RaiseOtherPropertyChanged(nameof(SelectedMessageProperties));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string SelectedMessageBody =>
|
public string SelectedMessageBody =>
|
||||||
SelectedMessage != null
|
SelectedMessage != null
|
||||||
? MessageBodyRenderer.Render(SelectedMessage.Body, SelectedMessage.Properties.ContentType())
|
? MessageBodyRenderer.Render(SelectedMessage.Body, SelectedMessage.Properties.ContentType)
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
public IDictionary<string, string>? SelectedMessageProperties => SelectedMessage?.Properties;
|
public IDictionary<string, string>? SelectedMessageProperties
|
||||||
|
{
|
||||||
|
get => selectedMessageProperties;
|
||||||
|
set => SetField(ref selectedMessageProperties, value);
|
||||||
|
}
|
||||||
|
|
||||||
public string Title => $"{subscriber.Exchange} - {subscriber.RoutingKey}";
|
public string Title => $"{subscriber.Exchange} - {subscriber.RoutingKey}";
|
||||||
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
public IEnumerable<TabToolbarCommand> ToolbarCommands => toolbarCommands;
|
||||||
@ -57,7 +56,7 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
|
|
||||||
uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||||
|
|
||||||
Messages = new ObservableCollection<MessageInfo>();
|
Messages = new ObservableCollection<ReceivedMessageInfo>();
|
||||||
clearCommand = new DelegateCommand(ClearExecute, ClearCanExecute);
|
clearCommand = new DelegateCommand(ClearExecute, ClearCanExecute);
|
||||||
|
|
||||||
toolbarCommands = new[]
|
toolbarCommands = new[]
|
||||||
@ -93,11 +92,18 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void UpdateSelectedMessageProperties()
|
||||||
|
{
|
||||||
|
SelectedMessageProperties = SelectedMessage != null
|
||||||
|
? MessagePropertiesRenderer.Render(SelectedMessage.Properties)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void RunFromUiScheduler(Action action)
|
private void RunFromUiScheduler(Action action)
|
||||||
{
|
{
|
||||||
_ = Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
|
_ = Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -116,9 +122,9 @@ namespace PettingZoo.UI.Tab.Subscriber
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public string Exchange { get; } = "dummy";
|
public string Exchange => "dummy";
|
||||||
public string RoutingKey { get; } = "dummy";
|
public string RoutingKey => "dummy";
|
||||||
|
|
||||||
#pragma warning disable CS0067
|
#pragma warning disable CS0067
|
||||||
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
public event EventHandler<MessageReceivedEventArgs>? MessageReceived;
|
||||||
#pragma warning restore CS0067
|
#pragma warning restore CS0067
|
||||||
|
Loading…
Reference in New Issue
Block a user