From 839ebc4ca99ae6bbf8ca6ffe8780b7346a3bf73c Mon Sep 17 00:00:00 2001 From: JKorf Date: Mon, 24 Nov 2025 21:22:02 +0100 Subject: [PATCH] wip --- CryptoExchange.Net/Clients/RestApiClient.cs | 35 ++++-- .../DynamicConverters/IRestMessageHandler.cs | 9 ++ .../MessageConverterTypes.cs | 117 ++++-------------- .../MessageEvalutorFieldReference.cs | 19 +++ .../MessageFieldReference.cs | 77 ++++++++++++ .../DynamicConverters/SearchResult.cs | 61 +++++++++ .../DynamicConverters/SearchResultItem.cs | 21 ++++ .../MessageHandlers/JsonRestMessageHandler.cs | 13 +- .../JsonSocketMessageHandler.cs | 5 +- .../Interfaces/IMessageProcessor.cs | 4 - .../Objects/Options/ApiOptions.cs | 3 +- .../Objects/Options/ExchangeOptions.cs | 3 +- .../Objects/Sockets/DataEvent.cs | 4 +- .../Sockets/CryptoExchangeWebSocketClient.cs | 1 - CryptoExchange.Net/Sockets/Query.cs | 13 +- CryptoExchange.Net/Sockets/Subscription.cs | 14 +-- .../Testing/RestIntegrationTest.cs | 7 +- .../Testing/SocketIntegrationTest.cs | 3 +- 18 files changed, 260 insertions(+), 149 deletions(-) create mode 100644 CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageEvalutorFieldReference.cs create mode 100644 CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageFieldReference.cs create mode 100644 CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResult.cs create mode 100644 CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResultItem.cs diff --git a/CryptoExchange.Net/Clients/RestApiClient.cs b/CryptoExchange.Net/Clients/RestApiClient.cs index 4d1942e..0031073 100644 --- a/CryptoExchange.Net/Clients/RestApiClient.cs +++ b/CryptoExchange.Net/Clients/RestApiClient.cs @@ -17,6 +17,7 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -97,9 +98,7 @@ namespace CryptoExchange.Net.Clients /// The message handler /// protected abstract IRestMessageHandler MessageHandler { get; } - - private static MediaTypeWithQualityHeaderValue AcceptJsonContent = new MediaTypeWithQualityHeaderValue(Constants.JsonContentHeader); - + /// /// ctor /// @@ -327,6 +326,9 @@ namespace CryptoExchange.Net.Clients return null; } + /// + /// Check rate limits for the request + /// protected virtual async Task RateLimitAsync( string host, int requestId, @@ -412,8 +414,7 @@ namespace CryptoExchange.Net.Clients var uri = new Uri(baseAddress.AppendPath(definition.Path) + queryString); var request = RequestFactory.Create(ClientOptions.HttpVersion, definition.Method, uri, requestId); -#warning Should be configurable - request.Accept = AcceptJsonContent; + request.Accept = MessageHandler.AcceptHeader; if (requestConfiguration.Headers != null) { @@ -473,7 +474,23 @@ namespace CryptoExchange.Net.Clients response = await request.GetResponseAsync(cancellationToken).ConfigureAwait(false); sw.Stop(); responseStream = await response.GetResponseStreamAsync().ConfigureAwait(false); + string? originalData = null; var outputOriginalData = ApiOptions.OutputOriginalData ?? ClientOptions.OutputOriginalData; + if (outputOriginalData) + { + // If we want to return the original string data from the stream, but still want to process it + // we'll need to copy it as the stream isn't seekable, and thus we can only read it once + var memoryStream = new MemoryStream(); + await responseStream.CopyToAsync(memoryStream).ConfigureAwait(false); + using var reader = new StreamReader(memoryStream, Encoding.UTF8,false, 4096, true); + memoryStream.Position = 0; + originalData = await reader.ReadToEndAsync().ConfigureAwait(false); + + // Continue processing from the memory stream since the response stream is already read and we can't seek it + responseStream.Close(); + memoryStream.Position = 0; + responseStream = memoryStream; + } if (!response.IsSuccessStatusCode && !requestDefinition.TryParseOnNonSuccess) { @@ -502,12 +519,12 @@ namespace CryptoExchange.Net.Clients responseStream).ConfigureAwait(false); } - return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, error); + return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, error); } if (typeof(T) == typeof(object)) // Success status code and expected empty response, assume it's correct - return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, 0, null/*accessor.OriginalDataAvailable ? accessor.GetOriginalString() : "[Data only available when OutputOriginal = true in client options]"*/, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, null); + return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, 0, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, null); // Data response received var parsedError = await MessageHandler.CheckForErrorResponse( @@ -527,11 +544,11 @@ namespace CryptoExchange.Net.Clients } // Success status code, but TryParseError determined it was an error response - return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, parsedError); + return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, default, parsedError); } var (deserializeResult, deserializeError) = await MessageHandler.TryDeserializeAsync(responseStream, state, cancellationToken).ConfigureAwait(false); - return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, deserializeResult, deserializeError); + return new WebCallResult(response.StatusCode, response.HttpVersion, response.ResponseHeaders, sw.Elapsed, response.ContentLength, originalData, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), ResultDataSource.Server, deserializeResult, deserializeError); } catch (HttpRequestException requestException) { diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IRestMessageHandler.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IRestMessageHandler.cs index d84c3e6..21661f9 100644 --- a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IRestMessageHandler.cs +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/IRestMessageHandler.cs @@ -14,6 +14,15 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters /// public interface IRestMessageHandler { + /// + /// The `accept` HTTP response header for the request + /// + MediaTypeWithQualityHeaderValue AcceptHeader { get; } + + /// + /// Create an object to keep state for a request + /// + /// object? CreateState(); /// diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs index ec86049..3e5b8b5 100644 --- a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageConverterTypes.cs @@ -4,26 +4,41 @@ using System.Text; namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters { - + /// + /// Message evaluator + /// public class MessageEvaluator { + /// + /// The priority of this evaluator, higher prio evaluators (with lower Priority number) will be checked for matches before lower ones + /// public int Priority { get; set; } + /// + /// Whether to immediately match the evaluator when it is matched. Can only be used when the evaluator has a single unique field to look for + /// public bool ForceIfFound { get; set; } - + /// + /// The fields this evaluator has to look for + /// public MessageFieldReference[] Fields { get; set; } - - public Func IdentifyMessageCallback { get; set; } + /// + /// The callback for getting the identifier string + /// + public Func? IdentifyMessageCallback { get; set; } + /// + /// The static identifier string to return when this evaluator is matched + /// public string? StaticIdentifier { get; set; } - - public string? IdentifyMessage(SearchResult result) + + internal string? IdentifyMessage(SearchResult result) { if (StaticIdentifier != null) return StaticIdentifier; - return IdentifyMessageCallback(result); + return IdentifyMessageCallback!(result); } - public bool Statisfied(SearchResult result) + internal bool Statisfied(SearchResult result) { foreach(var field in Fields) { @@ -34,90 +49,4 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters return true; } } - - public abstract class MessageFieldReference - { - public string SearchName { get; set; } - public int Depth { get; set; } = 1; - - public Func? Constraint { get; set; } - - public MessageFieldReference(string searchName) - { - SearchName = searchName; - } - } - - public class PropertyFieldReference : MessageFieldReference - { - public byte[] PropertyName { get; set; } - public bool ArrayValues { get; set; } - - public PropertyFieldReference(string propertyName) : base(propertyName) - { - PropertyName = Encoding.UTF8.GetBytes(propertyName); - } - } - - public class ArrayFieldReference : MessageFieldReference - { - public int ArrayIndex { get; set; } - - public ArrayFieldReference(string searchName, int depth, int index) : base(searchName) - { - Depth = depth; - ArrayIndex = index; - } - } - - public class MessageEvalutorFieldReference - { - public bool SkipReading { get; set; } - public bool OverlappingField { get; set; } - public MessageFieldReference Field { get; set; } - public MessageEvaluator? ForceEvaluator { get; set; } - } - - public class SearchResult - { - private List _items = new List(); - - public string FieldValue(string searchName) - { - foreach(var item in _items) - { - if (item.Field.SearchName.Equals(searchName, StringComparison.Ordinal)) - return item.Value; - } - - throw new Exception(""); // TODO - } - - public int Count => _items.Count; - - public void Clear() => _items.Clear(); - - public bool Contains(MessageFieldReference field) - { - foreach(var item in _items) - { - if (item.Field == field) - return true; - } - - return false; - } - - public void Write(MessageFieldReference field, string? value) => _items.Add(new SearchResultItem - { - Field = field, - Value = value - }); - } - - public struct SearchResultItem - { - public MessageFieldReference Field { get; set; } - public string? Value { get; set; } - } } diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageEvalutorFieldReference.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageEvalutorFieldReference.cs new file mode 100644 index 0000000..f2f2443 --- /dev/null +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageEvalutorFieldReference.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters +{ + internal class MessageEvalutorFieldReference + { + public bool SkipReading { get; set; } + public bool OverlappingField { get; set; } + public MessageFieldReference Field { get; set; } + public MessageEvaluator? ForceEvaluator { get; set; } + + public MessageEvalutorFieldReference(MessageFieldReference field) + { + Field = field; + } + } +} diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageFieldReference.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageFieldReference.cs new file mode 100644 index 0000000..72b55a6 --- /dev/null +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/MessageFieldReference.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters +{ + /// + /// Reference to a message field + /// + public abstract class MessageFieldReference + { + /// + /// The name for this search field + /// + public string SearchName { get; set; } + /// + /// The depth at which to look for this field + /// + public int Depth { get; set; } = 1; + /// + /// Callback to check if the field value matches an expected constraint + /// + public Func? Constraint { get; set; } + + /// + /// ctor + /// + public MessageFieldReference(string searchName) + { + SearchName = searchName; + } + } + + /// + /// Reference to a property message field + /// + public class PropertyFieldReference : MessageFieldReference + { + /// + /// The property name in the JSON + /// + public byte[] PropertyName { get; set; } + /// + /// Whether the property value is array values + /// + public bool ArrayValues { get; set; } + + /// + /// ctor + /// + public PropertyFieldReference(string propertyName) : base(propertyName) + { + PropertyName = Encoding.UTF8.GetBytes(propertyName); + } + } + + /// + /// Reference to an array message field + /// + public class ArrayFieldReference : MessageFieldReference + { + /// + /// The index in the array + /// + public int ArrayIndex { get; set; } + + /// + /// ctor + /// + public ArrayFieldReference(string searchName, int depth, int index) : base(searchName) + { + Depth = depth; + ArrayIndex = index; + } + } + +} diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResult.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResult.cs new file mode 100644 index 0000000..74f5822 --- /dev/null +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResult.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters +{ + /// + /// The results of a search for fields in a JSON message + /// + public class SearchResult + { + private List _items = new List(); + + /// + /// Get the value of a field + /// + public string? FieldValue(string searchName) + { + foreach (var item in _items) + { + if (item.Field.SearchName.Equals(searchName, StringComparison.Ordinal)) + return item.Value; + } + + throw new Exception(""); // TODO + } + + /// + /// The number of found search field values + /// + public int Count => _items.Count; + + /// + /// Clear the search result + /// + public void Clear() => _items.Clear(); + + /// + /// Whether the value for a specific field was found + /// + public bool Contains(MessageFieldReference field) + { + foreach (var item in _items) + { + if (item.Field == field) + return true; + } + + return false; + } + + /// + /// Write a value to the result + /// + public void Write(MessageFieldReference field, string? value) => _items.Add(new SearchResultItem + { + Field = field, + Value = value + }); + } +} diff --git a/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResultItem.cs b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResultItem.cs new file mode 100644 index 0000000..4618ccb --- /dev/null +++ b/CryptoExchange.Net/Converters/MessageParsing/DynamicConverters/SearchResultItem.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters +{ + /// + /// Search result value + /// + public struct SearchResultItem + { + /// + /// The field the values is for + /// + public MessageFieldReference Field { get; set; } + /// + /// The value of the field + /// + public string? Value { get; set; } + } +} diff --git a/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonRestMessageHandler.cs b/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonRestMessageHandler.cs index 5541583..a4f14f3 100644 --- a/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonRestMessageHandler.cs +++ b/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonRestMessageHandler.cs @@ -27,6 +27,8 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters /// public abstract class JsonRestMessageHandler : IRestMessageHandler { + private static MediaTypeWithQualityHeaderValue _acceptJsonContent = new MediaTypeWithQualityHeaderValue(Constants.JsonContentHeader); + /// /// Empty rate limit error /// @@ -37,7 +39,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters /// public abstract JsonSerializerOptions Options { get; } - public virtual object CreateState() => new JsonDocState(); + /// + public MediaTypeWithQualityHeaderValue AcceptHeader => _acceptJsonContent; + + /// + public virtual object CreateState() => new JsonDocState(); /// public virtual ValueTask ParseErrorRateLimitResponse( @@ -75,6 +81,9 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters HttpResponseHeaders responseHeaders, Stream responseStream) => new ValueTask((Error?)null); + /// + /// Read the response into a JsonDocument object + /// protected virtual async ValueTask<(Error?, JsonDocument?)> GetJsonDocument(Stream stream, object? state) { if (state is JsonDocState documentState && documentState.Document != null) @@ -106,7 +115,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters } else { - result = await JsonSerializer.DeserializeAsync(responseStream, Options)!.ConfigureAwait(false); + result = await JsonSerializer.DeserializeAsync(responseStream, Options)!.ConfigureAwait(false)!; } return (result, null); } diff --git a/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonSocketMessageHandler.cs b/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonSocketMessageHandler.cs index c02fb03..d13d60b 100644 --- a/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonSocketMessageHandler.cs +++ b/CryptoExchange.Net/Converters/SystemTextJson/MessageHandlers/JsonSocketMessageHandler.cs @@ -101,12 +101,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson } } - _searchFields.Add(new MessageEvalutorFieldReference + _searchFields.Add(new MessageEvalutorFieldReference(field) { SkipReading = evaluator.IdentifyMessageCallback == null && field.Constraint == null, ForceEvaluator = !existingSameSearchField.Any() ? (evaluator.ForceIfFound ? evaluator : null) : null, - OverlappingField = overlapping.Any(), - Field = field + OverlappingField = overlapping.Any() }); if (field.Depth > _maxSearchDepth) diff --git a/CryptoExchange.Net/Interfaces/IMessageProcessor.cs b/CryptoExchange.Net/Interfaces/IMessageProcessor.cs index 7991f1c..c91efe2 100644 --- a/CryptoExchange.Net/Interfaces/IMessageProcessor.cs +++ b/CryptoExchange.Net/Interfaces/IMessageProcessor.cs @@ -21,10 +21,6 @@ namespace CryptoExchange.Net.Interfaces /// public MessageMatcher MessageMatcher { get; } /// - /// The types the message processor deserializes to - /// - public HashSet DeserializationTypes { get; set; } - /// /// Handle a message /// CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object result, MessageHandlerLink matchedHandler); diff --git a/CryptoExchange.Net/Objects/Options/ApiOptions.cs b/CryptoExchange.Net/Objects/Options/ApiOptions.cs index aa63df7..a46fe79 100644 --- a/CryptoExchange.Net/Objects/Options/ApiOptions.cs +++ b/CryptoExchange.Net/Objects/Options/ApiOptions.cs @@ -8,7 +8,8 @@ namespace CryptoExchange.Net.Objects.Options public class ApiOptions { /// - /// If true, the CallResult and DataEvent objects will also include the originally received data in the OriginalData property + /// If true, the CallResult and DataEvent objects will also include the originally received string data in the OriginalData property. + /// Note that this comes at a performance cost /// public bool? OutputOriginalData { get; set; } diff --git a/CryptoExchange.Net/Objects/Options/ExchangeOptions.cs b/CryptoExchange.Net/Objects/Options/ExchangeOptions.cs index 2836de1..c766a3c 100644 --- a/CryptoExchange.Net/Objects/Options/ExchangeOptions.cs +++ b/CryptoExchange.Net/Objects/Options/ExchangeOptions.cs @@ -14,7 +14,8 @@ namespace CryptoExchange.Net.Objects.Options public ApiProxy? Proxy { get; set; } /// - /// If true, the CallResult and DataEvent objects will also include the originally received data in the OriginalData property + /// If true, the CallResult and DataEvent objects will also include the originally received string data in the OriginalData property. + /// Note that this comes at a performance cost /// public bool OutputOriginalData { get; set; } = false; diff --git a/CryptoExchange.Net/Objects/Sockets/DataEvent.cs b/CryptoExchange.Net/Objects/Sockets/DataEvent.cs index 9e52b1b..678077b 100644 --- a/CryptoExchange.Net/Objects/Sockets/DataEvent.cs +++ b/CryptoExchange.Net/Objects/Sockets/DataEvent.cs @@ -56,9 +56,9 @@ namespace CryptoExchange.Net.Objects.Sockets } } + /// public class DataEvent : DataEvent { - /// /// The received data deserialized into an object /// @@ -120,8 +120,6 @@ namespace CryptoExchange.Net.Objects.Sockets /// /// Copy the DataEvent to a new data type /// - /// The exchange the result is for - /// public ExchangeEvent AsExchangeEvent(string exchange, K data) { return new ExchangeEvent(exchange, this, data) diff --git a/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs b/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs index c53d3a5..6bff803 100644 --- a/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs +++ b/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs @@ -41,7 +41,6 @@ namespace CryptoExchange.Net.Sockets private ClientWebSocket _socket; private CancellationTokenSource _ctsSource; - private DateTime _lastReceivedMessagesUpdate; private Task? _processTask; private Task? _closeTask; private bool _stopRequested; diff --git a/CryptoExchange.Net/Sockets/Query.cs b/CryptoExchange.Net/Sockets/Query.cs index e249b47..e285063 100644 --- a/CryptoExchange.Net/Sockets/Query.cs +++ b/CryptoExchange.Net/Sockets/Query.cs @@ -59,22 +59,11 @@ namespace CryptoExchange.Net.Sockets /// Response /// public object? Response { get; set; } -#warning check if there is a better solution for this in combination with the MessageMatcher - public HashSet DeserializationTypes { get; set; } - private MessageMatcher _matcher; /// /// Matcher for this subscription /// - public MessageMatcher MessageMatcher - { - get => _matcher; - set - { - _matcher = value; - DeserializationTypes = new HashSet(MessageMatcher.HandlerLinks.Select(x => x.DeserializationType)); - } - } + public MessageMatcher MessageMatcher { get; set; } /// /// The query request object diff --git a/CryptoExchange.Net/Sockets/Subscription.cs b/CryptoExchange.Net/Sockets/Subscription.cs index 981dff2..5779015 100644 --- a/CryptoExchange.Net/Sockets/Subscription.cs +++ b/CryptoExchange.Net/Sockets/Subscription.cs @@ -35,8 +35,6 @@ namespace CryptoExchange.Net.Sockets /// public bool UserSubscription { get; set; } - public HashSet DeserializationTypes { get; set; } - private SubscriptionStatus _status; /// /// Current subscription status @@ -74,20 +72,10 @@ namespace CryptoExchange.Net.Sockets /// public bool Authenticated { get; } - - private MessageMatcher _matcher; /// /// Matcher for this subscription /// - public MessageMatcher MessageMatcher - { - get => _matcher; - set - { - _matcher = value; - DeserializationTypes = new HashSet(MessageMatcher.HandlerLinks.Select(x => x.DeserializationType)); - } - } + public MessageMatcher MessageMatcher { get; set; } /// /// Cancellation token registration diff --git a/CryptoExchange.Net/Testing/RestIntegrationTest.cs b/CryptoExchange.Net/Testing/RestIntegrationTest.cs index f4a603d..8653e35 100644 --- a/CryptoExchange.Net/Testing/RestIntegrationTest.cs +++ b/CryptoExchange.Net/Testing/RestIntegrationTest.cs @@ -17,8 +17,6 @@ namespace CryptoExchange.Net.Testing /// /// Get a client instance /// - /// - /// public abstract TClient GetClient(ILoggerFactory loggerFactory, bool newDeserialization); /// @@ -59,14 +57,15 @@ namespace CryptoExchange.Net.Testing /// Execute a REST endpoint call and check for any errors or warnings. /// /// Type of response + /// Whether to use the new deserialization method /// The call expression /// Whether this is an authenticated request - public async Task RunAndCheckResult(bool newDeserialization, Expression>>> expression, bool authRequest) + public async Task RunAndCheckResult(bool useNewDeserialization, Expression>>> expression, bool authRequest) { if (!ShouldRun()) return; - var client = CreateClient(newDeserialization); + var client = CreateClient(useNewDeserialization); var expressionBody = (MethodCallExpression)expression.Body; if (authRequest && !Authenticated) diff --git a/CryptoExchange.Net/Testing/SocketIntegrationTest.cs b/CryptoExchange.Net/Testing/SocketIntegrationTest.cs index d003148..e84c129 100644 --- a/CryptoExchange.Net/Testing/SocketIntegrationTest.cs +++ b/CryptoExchange.Net/Testing/SocketIntegrationTest.cs @@ -19,8 +19,6 @@ namespace CryptoExchange.Net.Testing /// /// Get a client instance /// - /// - /// public abstract TClient GetClient(ILoggerFactory loggerFactory, bool newDeserialization); /// @@ -61,6 +59,7 @@ namespace CryptoExchange.Net.Testing /// Execute a REST endpoint call and check for any errors or warnings. /// /// Type of the update + /// Whether to use the new deserialization method /// The call expression /// Whether an update is expected /// Whether this is an authenticated request