Skip to content

Commit ea057a7

Browse files
author
Ahmad Noman Musleh
committed
Added new SendMessage method overload without payload type
1 parent 26fb7d2 commit ea057a7

4 files changed

Lines changed: 70 additions & 13 deletions

File tree

src/OpenAPI.Net/Helpers/MessageFactory.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static ProtoMessage GetMessage<T>(this T message, ProtoOAPayloadType payl
4040
public static IMessage GetMessage(ProtoMessage protoMessage)
4141
{
4242
var payload = protoMessage.Payload;
43-
43+
4444
return protoMessage.PayloadType switch
4545
{
4646
(int)ProtoOAPayloadType.ProtoOaErrorRes => ProtoOAErrorRes.Parser.ParseFrom(payload),
@@ -89,7 +89,14 @@ public static IMessage GetMessage(ProtoMessage protoMessage)
8989
};
9090
}
9191

92-
private static ProtoMessage GetMessage(uint payloadType, ByteString payload, string clientMessageId = null)
92+
/// <summary>
93+
/// Returns a ProtoMessage based on your provided parameters
94+
/// </summary>
95+
/// <param name="payloadType">The message payloadType as unint</param>
96+
/// <param name="payload">The message payload as a ByteString</param>
97+
/// <param name="clientMessageId">The client message ID for ProtoMessage</param>
98+
/// <returns>ProtoMessage</returns>
99+
public static ProtoMessage GetMessage(uint payloadType, ByteString payload, string clientMessageId = null)
93100
{
94101
var message = new ProtoMessage
95102
{
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using Google.Protobuf;
2+
using System;
3+
using System.Reflection;
4+
5+
namespace OpenAPI.Net.Helpers
6+
{
7+
public static class MessagePayloadTypeExtension
8+
{
9+
/// <summary>
10+
/// This method returns the payload type of a message
11+
/// </summary>
12+
/// <typeparam name="T">IMessage</typeparam>
13+
/// <param name="message">The message</param>
14+
/// <returns>uint (Payload Type)</returns>
15+
/// <exception cref="InvalidOperationException"></exception>
16+
public static uint GetPayloadType<T>(this T message) where T : IMessage
17+
{
18+
PropertyInfo property;
19+
20+
try
21+
{
22+
property = message.GetType().GetProperty("PayloadType");
23+
}
24+
catch (Exception ex) when (ex is AmbiguousMatchException || ex is ArgumentNullException)
25+
{
26+
throw new InvalidOperationException($"Couldn't get the PayloadType of the message {message}", ex);
27+
}
28+
29+
return (uint)property.GetValue(message);
30+
}
31+
}
32+
}

src/OpenAPI.Net/OpenAPI.Net.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<PackageTags>cTrader, Open API, Spotware</PackageTags>
1010
<Description>A .NET RX library for Spotware Open API</Description>
1111
<PackageId>Spotware.OpenAPI.Net</PackageId>
12-
<Version>1.3.6-rc0</Version>
12+
<Version>1.3.6-rc1</Version>
1313
<Platforms>AnyCPU</Platforms>
1414
<Company>Spotware</Company>
1515
<Authors>Spotware</Authors>

src/OpenAPI.Net/OpenClient.cs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public sealed class OpenClient : IDisposable, IObservable<IMessage>
2626

2727
private readonly ConcurrentDictionary<int, IObserver<IMessage>> _observers = new ConcurrentDictionary<int, IObserver<IMessage>>();
2828

29-
private readonly CancellationTokenSource _messagesCancellationTokenSource = new CancellationTokenSource();
29+
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
3030

3131
private readonly TimeSpan _requestDelay;
3232

@@ -36,8 +36,6 @@ public sealed class OpenClient : IDisposable, IObservable<IMessage>
3636

3737
private SslStream _sslStream;
3838

39-
private IDisposable _listenerDisposable;
40-
4139
private IDisposable _heartbeatDisposable;
4240

4341
private IDisposable _webSocketDisconnectionHappenedDisposable;
@@ -129,7 +127,7 @@ public async Task Connect()
129127
await ConnectTcp();
130128
}
131129

132-
_ = StartSendingMessages(_messagesCancellationTokenSource.Token);
130+
_ = StartSendingMessages(_cancellationTokenSource.Token);
133131

134132
_heartbeatDisposable = Observable.Interval(_heartbeatInerval).DoWhile(() => !IsDisposed)
135133
.Subscribe(x => SendHeartbeat());
@@ -180,7 +178,7 @@ private async Task ConnectTcp()
180178

181179
await _sslStream.AuthenticateAsClientAsync(Host).ConfigureAwait(false);
182180

183-
_ = ReadTcp();
181+
_ = ReadTcp(_cancellationTokenSource.Token);
184182
}
185183

186184
/// <summary>
@@ -197,6 +195,24 @@ public IDisposable Subscribe(IObserver<IMessage> observer)
197195
return Disposable.Create(() => OnObserverDispose(observer));
198196
}
199197

198+
/// <summary>
199+
/// This method will insert your message on messages queue, it will not send the message instantly
200+
/// By using this overload of SendMessage method you avoid passing the message payload type
201+
/// and it gets the payload from message itself
202+
/// </summary>
203+
/// <typeparam name="T">Message Type</typeparam>
204+
/// <param name="message">Message</param>
205+
/// <param name="clientMsgId">The client message ID (optional)</param>
206+
/// <exception cref="InvalidOperationException">If getting message payload type fails</exception>
207+
/// <returns>Task</returns>
208+
public async Task SendMessage<T>(T message, string clientMsgId = null) where T :
209+
IMessage
210+
{
211+
var protoMessage = MessageFactory.GetMessage(message.GetPayloadType(), message.ToByteString(), clientMsgId);
212+
213+
await SendMessage(protoMessage);
214+
}
215+
200216
/// <summary>
201217
/// This method will insert your message on messages queue, it will not send the message instantly
202218
/// </summary>
@@ -316,9 +332,8 @@ public void Dispose()
316332
IsDisposed = true;
317333

318334
_heartbeatDisposable?.Dispose();
319-
_listenerDisposable?.Dispose();
320335

321-
_messagesCancellationTokenSource.Cancel();
336+
_cancellationTokenSource.Cancel();
322337

323338
_messagesChannel.Writer.TryComplete();
324339

@@ -346,7 +361,7 @@ public void Dispose()
346361
/// This method will read the TCP stream for incoming messages
347362
/// </summary>
348363
/// <returns>Task</returns>
349-
private async Task ReadTcp()
364+
private async Task ReadTcp(CancellationToken cancellationToken)
350365
{
351366
while (!IsDisposed)
352367
{
@@ -360,7 +375,7 @@ private async Task ReadTcp()
360375
{
361376
var count = lengthArray.Length - readBytes;
362377

363-
readBytes += await _sslStream.ReadAsync(lengthArray, readBytes, count).ConfigureAwait(false);
378+
readBytes += await _sslStream.ReadAsync(lengthArray, readBytes, count, cancellationToken).ConfigureAwait(false);
364379
}
365380
while (readBytes < lengthArray.Length);
366381

@@ -378,14 +393,17 @@ private async Task ReadTcp()
378393
{
379394
var count = data.Length - readBytes;
380395

381-
readBytes += await _sslStream.ReadAsync(data, readBytes, count).ConfigureAwait(false);
396+
readBytes += await _sslStream.ReadAsync(data, readBytes, count, cancellationToken).ConfigureAwait(false);
382397
}
383398
while (readBytes < length);
384399

385400
var message = ProtoMessage.Parser.ParseFrom(data);
386401

387402
OnNext(message);
388403
}
404+
catch (TaskCanceledException)
405+
{
406+
}
389407
catch (Exception ex)
390408
{
391409
var readException = new ReadException(ex);

0 commit comments

Comments
 (0)