mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-12-14 01:33:26 +00:00
wip
This commit is contained in:
parent
07fdee1740
commit
839ebc4ca9
@ -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
|
||||
/// </summary>
|
||||
protected abstract IRestMessageHandler MessageHandler { get; }
|
||||
|
||||
private static MediaTypeWithQualityHeaderValue AcceptJsonContent = new MediaTypeWithQualityHeaderValue(Constants.JsonContentHeader);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
@ -327,6 +326,9 @@ namespace CryptoExchange.Net.Clients
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check rate limits for the request
|
||||
/// </summary>
|
||||
protected virtual async Task<Error?> 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<T>(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<T>(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<T>(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<T>(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<T>(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<T>(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<T>(responseStream, state, cancellationToken).ConfigureAwait(false);
|
||||
return new WebCallResult<T>(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<T>(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)
|
||||
{
|
||||
|
||||
@ -14,6 +14,15 @@ namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
/// </summary>
|
||||
public interface IRestMessageHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// The `accept` HTTP response header for the request
|
||||
/// </summary>
|
||||
MediaTypeWithQualityHeaderValue AcceptHeader { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an object to keep state for a request
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
object? CreateState();
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -4,26 +4,41 @@ using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Message evaluator
|
||||
/// </summary>
|
||||
public class MessageEvaluator
|
||||
{
|
||||
/// <summary>
|
||||
/// The priority of this evaluator, higher prio evaluators (with lower Priority number) will be checked for matches before lower ones
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
public bool ForceIfFound { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The fields this evaluator has to look for
|
||||
/// </summary>
|
||||
public MessageFieldReference[] Fields { get; set; }
|
||||
|
||||
public Func<SearchResult, string> IdentifyMessageCallback { get; set; }
|
||||
/// <summary>
|
||||
/// The callback for getting the identifier string
|
||||
/// </summary>
|
||||
public Func<SearchResult, string>? IdentifyMessageCallback { get; set; }
|
||||
/// <summary>
|
||||
/// The static identifier string to return when this evaluator is matched
|
||||
/// </summary>
|
||||
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<string?, bool>? 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<SearchResultItem> _items = new List<SearchResultItem>();
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to a message field
|
||||
/// </summary>
|
||||
public abstract class MessageFieldReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The name for this search field
|
||||
/// </summary>
|
||||
public string SearchName { get; set; }
|
||||
/// <summary>
|
||||
/// The depth at which to look for this field
|
||||
/// </summary>
|
||||
public int Depth { get; set; } = 1;
|
||||
/// <summary>
|
||||
/// Callback to check if the field value matches an expected constraint
|
||||
/// </summary>
|
||||
public Func<string?, bool>? Constraint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public MessageFieldReference(string searchName)
|
||||
{
|
||||
SearchName = searchName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to a property message field
|
||||
/// </summary>
|
||||
public class PropertyFieldReference : MessageFieldReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The property name in the JSON
|
||||
/// </summary>
|
||||
public byte[] PropertyName { get; set; }
|
||||
/// <summary>
|
||||
/// Whether the property value is array values
|
||||
/// </summary>
|
||||
public bool ArrayValues { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public PropertyFieldReference(string propertyName) : base(propertyName)
|
||||
{
|
||||
PropertyName = Encoding.UTF8.GetBytes(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to an array message field
|
||||
/// </summary>
|
||||
public class ArrayFieldReference : MessageFieldReference
|
||||
{
|
||||
/// <summary>
|
||||
/// The index in the array
|
||||
/// </summary>
|
||||
public int ArrayIndex { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ctor
|
||||
/// </summary>
|
||||
public ArrayFieldReference(string searchName, int depth, int index) : base(searchName)
|
||||
{
|
||||
Depth = depth;
|
||||
ArrayIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// The results of a search for fields in a JSON message
|
||||
/// </summary>
|
||||
public class SearchResult
|
||||
{
|
||||
private List<SearchResultItem> _items = new List<SearchResultItem>();
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a field
|
||||
/// </summary>
|
||||
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
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of found search field values
|
||||
/// </summary>
|
||||
public int Count => _items.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Clear the search result
|
||||
/// </summary>
|
||||
public void Clear() => _items.Clear();
|
||||
|
||||
/// <summary>
|
||||
/// Whether the value for a specific field was found
|
||||
/// </summary>
|
||||
public bool Contains(MessageFieldReference field)
|
||||
{
|
||||
foreach (var item in _items)
|
||||
{
|
||||
if (item.Field == field)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a value to the result
|
||||
/// </summary>
|
||||
public void Write(MessageFieldReference field, string? value) => _items.Add(new SearchResultItem
|
||||
{
|
||||
Field = field,
|
||||
Value = value
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CryptoExchange.Net.Converters.MessageParsing.DynamicConverters
|
||||
{
|
||||
/// <summary>
|
||||
/// Search result value
|
||||
/// </summary>
|
||||
public struct SearchResultItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The field the values is for
|
||||
/// </summary>
|
||||
public MessageFieldReference Field { get; set; }
|
||||
/// <summary>
|
||||
/// The value of the field
|
||||
/// </summary>
|
||||
public string? Value { get; set; }
|
||||
}
|
||||
}
|
||||
@ -27,6 +27,8 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters
|
||||
/// </summary>
|
||||
public abstract class JsonRestMessageHandler : IRestMessageHandler
|
||||
{
|
||||
private static MediaTypeWithQualityHeaderValue _acceptJsonContent = new MediaTypeWithQualityHeaderValue(Constants.JsonContentHeader);
|
||||
|
||||
/// <summary>
|
||||
/// Empty rate limit error
|
||||
/// </summary>
|
||||
@ -37,7 +39,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters
|
||||
/// </summary>
|
||||
public abstract JsonSerializerOptions Options { get; }
|
||||
|
||||
public virtual object CreateState() => new JsonDocState();
|
||||
/// <inheritdoc />
|
||||
public MediaTypeWithQualityHeaderValue AcceptHeader => _acceptJsonContent;
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual object CreateState() => new JsonDocState();
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual ValueTask<ServerRateLimitError> ParseErrorRateLimitResponse(
|
||||
@ -75,6 +81,9 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageConverters
|
||||
HttpResponseHeaders responseHeaders,
|
||||
Stream responseStream) => new ValueTask<Error?>((Error?)null);
|
||||
|
||||
/// <summary>
|
||||
/// Read the response into a JsonDocument object
|
||||
/// </summary>
|
||||
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<T>(responseStream, Options)!.ConfigureAwait(false);
|
||||
result = await JsonSerializer.DeserializeAsync<T>(responseStream, Options)!.ConfigureAwait(false)!;
|
||||
}
|
||||
return (result, null);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -21,10 +21,6 @@ namespace CryptoExchange.Net.Interfaces
|
||||
/// </summary>
|
||||
public MessageMatcher MessageMatcher { get; }
|
||||
/// <summary>
|
||||
/// The types the message processor deserializes to
|
||||
/// </summary>
|
||||
public HashSet<Type> DeserializationTypes { get; set; }
|
||||
/// <summary>
|
||||
/// Handle a message
|
||||
/// </summary>
|
||||
CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object result, MessageHandlerLink matchedHandler);
|
||||
|
||||
@ -8,7 +8,8 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
public class ApiOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
public bool? OutputOriginalData { get; set; }
|
||||
|
||||
|
||||
@ -14,7 +14,8 @@ namespace CryptoExchange.Net.Objects.Options
|
||||
public ApiProxy? Proxy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
public bool OutputOriginalData { get; set; } = false;
|
||||
|
||||
|
||||
@ -56,9 +56,9 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public class DataEvent<T> : DataEvent
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// The received data deserialized into an object
|
||||
/// </summary>
|
||||
@ -120,8 +120,6 @@ namespace CryptoExchange.Net.Objects.Sockets
|
||||
/// <summary>
|
||||
/// Copy the DataEvent to a new data type
|
||||
/// </summary>
|
||||
/// <param name="exchange">The exchange the result is for</param>
|
||||
/// <returns></returns>
|
||||
public ExchangeEvent<K> AsExchangeEvent<K>(string exchange, K data)
|
||||
{
|
||||
return new ExchangeEvent<K>(exchange, this, data)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -59,22 +59,11 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// Response
|
||||
/// </summary>
|
||||
public object? Response { get; set; }
|
||||
#warning check if there is a better solution for this in combination with the MessageMatcher
|
||||
public HashSet<Type> DeserializationTypes { get; set; }
|
||||
|
||||
private MessageMatcher _matcher;
|
||||
/// <summary>
|
||||
/// Matcher for this subscription
|
||||
/// </summary>
|
||||
public MessageMatcher MessageMatcher
|
||||
{
|
||||
get => _matcher;
|
||||
set
|
||||
{
|
||||
_matcher = value;
|
||||
DeserializationTypes = new HashSet<Type>(MessageMatcher.HandlerLinks.Select(x => x.DeserializationType));
|
||||
}
|
||||
}
|
||||
public MessageMatcher MessageMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The query request object
|
||||
|
||||
@ -35,8 +35,6 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// </summary>
|
||||
public bool UserSubscription { get; set; }
|
||||
|
||||
public HashSet<Type> DeserializationTypes { get; set; }
|
||||
|
||||
private SubscriptionStatus _status;
|
||||
/// <summary>
|
||||
/// Current subscription status
|
||||
@ -74,20 +72,10 @@ namespace CryptoExchange.Net.Sockets
|
||||
/// </summary>
|
||||
public bool Authenticated { get; }
|
||||
|
||||
|
||||
private MessageMatcher _matcher;
|
||||
/// <summary>
|
||||
/// Matcher for this subscription
|
||||
/// </summary>
|
||||
public MessageMatcher MessageMatcher
|
||||
{
|
||||
get => _matcher;
|
||||
set
|
||||
{
|
||||
_matcher = value;
|
||||
DeserializationTypes = new HashSet<Type>(MessageMatcher.HandlerLinks.Select(x => x.DeserializationType));
|
||||
}
|
||||
}
|
||||
public MessageMatcher MessageMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cancellation token registration
|
||||
|
||||
@ -17,8 +17,6 @@ namespace CryptoExchange.Net.Testing
|
||||
/// <summary>
|
||||
/// Get a client instance
|
||||
/// </summary>
|
||||
/// <param name="loggerFactory"></param>
|
||||
/// <returns></returns>
|
||||
public abstract TClient GetClient(ILoggerFactory loggerFactory, bool newDeserialization);
|
||||
|
||||
/// <summary>
|
||||
@ -59,14 +57,15 @@ namespace CryptoExchange.Net.Testing
|
||||
/// Execute a REST endpoint call and check for any errors or warnings.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of response</typeparam>
|
||||
/// <param name="useNewDeserialization">Whether to use the new deserialization method</param>
|
||||
/// <param name="expression">The call expression</param>
|
||||
/// <param name="authRequest">Whether this is an authenticated request</param>
|
||||
public async Task RunAndCheckResult<T>(bool newDeserialization, Expression<Func<TClient, Task<WebCallResult<T>>>> expression, bool authRequest)
|
||||
public async Task RunAndCheckResult<T>(bool useNewDeserialization, Expression<Func<TClient, Task<WebCallResult<T>>>> expression, bool authRequest)
|
||||
{
|
||||
if (!ShouldRun())
|
||||
return;
|
||||
|
||||
var client = CreateClient(newDeserialization);
|
||||
var client = CreateClient(useNewDeserialization);
|
||||
|
||||
var expressionBody = (MethodCallExpression)expression.Body;
|
||||
if (authRequest && !Authenticated)
|
||||
|
||||
@ -19,8 +19,6 @@ namespace CryptoExchange.Net.Testing
|
||||
/// <summary>
|
||||
/// Get a client instance
|
||||
/// </summary>
|
||||
/// <param name="loggerFactory"></param>
|
||||
/// <returns></returns>
|
||||
public abstract TClient GetClient(ILoggerFactory loggerFactory, bool newDeserialization);
|
||||
|
||||
/// <summary>
|
||||
@ -61,6 +59,7 @@ namespace CryptoExchange.Net.Testing
|
||||
/// Execute a REST endpoint call and check for any errors or warnings.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the update</typeparam>
|
||||
/// <param name="useNewDeserialization">Whether to use the new deserialization method</param>
|
||||
/// <param name="expression">The call expression</param>
|
||||
/// <param name="expectUpdate">Whether an update is expected</param>
|
||||
/// <param name="authRequest">Whether this is an authenticated request</param>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user