mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-12 17:03:10 +00:00
d079796020
Performance update: Authentication Added Ed25519 signing support for NET8.0 and newer Added static methods on ApiCredentials to create credentials of a specific type Added static ApiCredentials.ReadFromFile method to read a key from file Added required abstract SupportedCredentialTypes property on AuthenticationProvider base class General Performance Added checks before logging statements to prevent overhead of building the log string if logging is not needed Added ExchangeHelpers.ProcessQueuedAsync method to process updates async Replaced locking object types from object to Lock in NET9.0 and newer Replaced some Task response types with ValueTask to prevent allocation overhead on hot paths Updated Json ArrayConverter to reduce some allocation overhead Updated Json BoolConverter to prevent boxing Updated Json DateTimeConverter to prevent boxing Updated Json EnumConverter caching to reduce lookup overhead Updated ExtensionMethods.CreateParamString to reduce allocations Updated ExtensionMethods.AppendPath to reduce overhead REST Refactored REST message processing to separate IRestMessageHandler instance Split RestApiClient.PrepareAsync into CheckTimeSync and RateLimitAsync Updated IRequest.Accept type from string to MediaTypeWithQualityHeaderValue to prevent creation on each request Updated IRequest.GetHeaders response type from KeyValuePair<string, string[]>[] to HttpRequestHeaders to prevent additional mapping Updated IResponse.ResponseHeaders type from KeyValuePair<string, string[]>[] to HttpResponseHeaders to prevent additional mapping Updated WebCallResult RequestHeaders and ResponseHeaders types to HttpRequestHeaders and HttpResponseHeaders Removed unnecessary empty dictionary initializations for each request Removed CallResult creation in internal methods to prevent having to create multiple versions for different result types Socket Added HighPerformance websocket client implementation which significantly reduces memory overhead and improves speed but with certain limitations Added MaxIndividualSubscriptionsPerConnection setting in SocketApiClient to limit the number of individual stream subscriptions on a connection Added SocketIndividualSubscriptionCombineTarget option to set the target number of individual stream subscriptions per connection Added new websocket message handling logic which is faster and reduces memory allocation Added UseUpdatedDeserialization option to toggle between updated deserialization and old deserialization Added Exchange property to DataEvent to prevent additional mapping overhead for Shared apis Refactored message callback to be sync instead of async to prevent async overhead Refactored CryptoExchangeWebSocketClient.IncomingKbps calculation to significantly reduce overhead Moved websocket client creation from SocketApiClient to SocketConnection Removed DataEvent.As and DataEvent.ToCallResult methods in favor of single ToType method Removed DataEvent creation on lower levels to prevent having to create multiple versions for different result types Removed Subscription<TSubResponse, TUnsubResponse> as its no longer used Other Added null check to ParameterCollection for required parameters Added Net10.0 target framework Updated dependency versions Updated Shared asset aliases check to be culture invariant Updated Error string representation Updated some namespaces Updated SymbolOrderBook processing of buffered updates to prevent additional allocation Removed ExchangeEvent type which is no longer needed Removed unused usings
590 lines
21 KiB
C#
590 lines
21 KiB
C#
using CryptoExchange.Net.SharedApis;
|
|
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Text;
|
|
|
|
namespace CryptoExchange.Net.Objects
|
|
{
|
|
/// <summary>
|
|
/// The result of an operation
|
|
/// </summary>
|
|
public class CallResult
|
|
{
|
|
/// <summary>
|
|
/// Static success result
|
|
/// </summary>
|
|
public static CallResult SuccessResult { get; } = new CallResult(null);
|
|
|
|
/// <summary>
|
|
/// An error if the call didn't succeed, will always be filled if Success = false
|
|
/// </summary>
|
|
public Error? Error { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// Whether the call was successful
|
|
/// </summary>
|
|
public bool Success => Error == null;
|
|
|
|
/// <summary>
|
|
/// ctor
|
|
/// </summary>
|
|
/// <param name="error"></param>
|
|
public CallResult(Error? error)
|
|
{
|
|
Error = error;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
|
|
/// </summary>
|
|
/// <param name="obj"></param>
|
|
public static implicit operator bool(CallResult obj)
|
|
{
|
|
return obj?.Success == true;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString()
|
|
{
|
|
return Success ? $"Success" : $"Error: {Error}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The result of an operation
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
public class CallResult<T>: CallResult
|
|
{
|
|
/// <summary>
|
|
/// The data returned by the call, only available when Success = true
|
|
/// </summary>
|
|
public T Data { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// The original data returned by the call, only available when `OutputOriginalData` is set to `true` in the client options
|
|
/// </summary>
|
|
public string? OriginalData { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// ctor
|
|
/// </summary>
|
|
/// <param name="data"></param>
|
|
/// <param name="originalData"></param>
|
|
/// <param name="error"></param>
|
|
#pragma warning disable 8618
|
|
public CallResult([AllowNull]T data, string? originalData, Error? error): base(error)
|
|
#pragma warning restore 8618
|
|
{
|
|
OriginalData = originalData;
|
|
#pragma warning disable 8601
|
|
Data = data;
|
|
#pragma warning restore 8601
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new data result
|
|
/// </summary>
|
|
/// <param name="data">The data to return</param>
|
|
public CallResult(T data) : this(data, null, null) { }
|
|
|
|
/// <summary>
|
|
/// Create a new error result
|
|
/// </summary>
|
|
/// <param name="error">The error to return</param>
|
|
public CallResult(Error error) : this(default, null, error) { }
|
|
|
|
/// <summary>
|
|
/// Create a new error result
|
|
/// </summary>
|
|
/// <param name="error">The error to return</param>
|
|
/// <param name="originalData">The original response data</param>
|
|
public CallResult(Error error, string? originalData) : this(default, originalData, error) { }
|
|
|
|
/// <summary>
|
|
/// Overwrite bool check so we can use if(callResult) instead of if(callResult.Success)
|
|
/// </summary>
|
|
/// <param name="obj"></param>
|
|
public static implicit operator bool(CallResult<T> obj)
|
|
{
|
|
return obj?.Success == true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether the call was successful or not. Useful for nullability checking.
|
|
/// </summary>
|
|
/// <param name="data">The data returned by the call.</param>
|
|
/// <param name="error"><see cref="Error"/> on failure.</param>
|
|
/// <returns><c>true</c> when <see cref="CallResult{T}"/> succeeded, <c>false</c> otherwise.</returns>
|
|
public bool GetResultOrError([MaybeNullWhen(false)] out T data, [NotNullWhen(false)] out Error? error)
|
|
{
|
|
if (Success)
|
|
{
|
|
data = Data!;
|
|
error = null;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
data = default;
|
|
error = Error!;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="data">The data of the new type</param>
|
|
/// <returns></returns>
|
|
public CallResult<K> As<K>([AllowNull] K data)
|
|
{
|
|
return new CallResult<K>(data, OriginalData, Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy as a dataless result
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public CallResult AsDataless()
|
|
{
|
|
return SuccessResult;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy as a dataless result
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public CallResult AsDatalessError(Error error)
|
|
{
|
|
return new CallResult(error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the CallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="data">The data</param>
|
|
/// <param name="error">The error returned</param>
|
|
/// <returns></returns>
|
|
public CallResult<K> AsErrorWithData<K>(Error error, K data)
|
|
{
|
|
return new CallResult<K>(data, OriginalData, error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="error">The error to return</param>
|
|
/// <returns></returns>
|
|
public CallResult<K> AsError<K>(Error error)
|
|
{
|
|
return new CallResult<K>(default, OriginalData, error);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString()
|
|
{
|
|
return Success ? $"Success" : $"Error: {Error}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The result of a request
|
|
/// </summary>
|
|
public class WebCallResult : CallResult
|
|
{
|
|
/// <summary>
|
|
/// The request http method
|
|
/// </summary>
|
|
public HttpMethod? RequestMethod { get; set; }
|
|
|
|
/// <summary>
|
|
/// HTTP protocol version
|
|
/// </summary>
|
|
public Version? HttpVersion { get; set; }
|
|
|
|
/// <summary>
|
|
/// The headers sent with the request
|
|
/// </summary>
|
|
public HttpRequestHeaders? RequestHeaders { get; set; }
|
|
|
|
/// <summary>
|
|
/// The request id
|
|
/// </summary>
|
|
public int? RequestId { get; set; }
|
|
|
|
/// <summary>
|
|
/// The url which was requested
|
|
/// </summary>
|
|
public string? RequestUrl { get; set; }
|
|
|
|
/// <summary>
|
|
/// The body of the request
|
|
/// </summary>
|
|
public string? RequestBody { get; set; }
|
|
|
|
/// <summary>
|
|
/// The original data returned by the call, only available when `OutputOriginalData` is set to `true` in the client options
|
|
/// </summary>
|
|
public string? OriginalData { get; internal set; }
|
|
|
|
/// <summary>
|
|
/// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
|
|
/// </summary>
|
|
public HttpStatusCode? ResponseStatusCode { get; set; }
|
|
|
|
/// <summary>
|
|
/// The response headers
|
|
/// </summary>
|
|
public HttpResponseHeaders? ResponseHeaders { get; set; }
|
|
|
|
/// <summary>
|
|
/// The time between sending the request and receiving the response
|
|
/// </summary>
|
|
public TimeSpan? ResponseTime { get; set; }
|
|
|
|
/// <summary>
|
|
/// ctor
|
|
/// </summary>
|
|
public WebCallResult(
|
|
HttpStatusCode? code,
|
|
Version? httpVersion,
|
|
HttpResponseHeaders? responseHeaders,
|
|
TimeSpan? responseTime,
|
|
string? originalData,
|
|
int? requestId,
|
|
string? requestUrl,
|
|
string? requestBody,
|
|
HttpMethod? requestMethod,
|
|
HttpRequestHeaders? requestHeaders,
|
|
Error? error) : base(error)
|
|
{
|
|
ResponseStatusCode = code;
|
|
HttpVersion = httpVersion;
|
|
ResponseHeaders = responseHeaders;
|
|
ResponseTime = responseTime;
|
|
RequestId = requestId;
|
|
OriginalData = originalData;
|
|
|
|
RequestUrl = requestUrl;
|
|
RequestBody = requestBody;
|
|
RequestHeaders = requestHeaders;
|
|
RequestMethod = requestMethod;
|
|
}
|
|
|
|
/// <summary>
|
|
/// ctor
|
|
/// </summary>
|
|
/// <param name="error"></param>
|
|
public WebCallResult(Error error): base(error) { }
|
|
|
|
/// <summary>
|
|
/// Return the result as an error result
|
|
/// </summary>
|
|
/// <param name="error">The error returned</param>
|
|
/// <returns></returns>
|
|
public WebCallResult AsError(Error error)
|
|
{
|
|
return new WebCallResult(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="data">The data of the new type</param>
|
|
/// <returns></returns>
|
|
public WebCallResult<K> As<K>([AllowNull] K data)
|
|
{
|
|
return new WebCallResult<K>(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, 0, null, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, ResultDataSource.Server, data, Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="tradeMode">Trade mode the result applies to</param>
|
|
/// <param name="data">The data</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode tradeMode, [AllowNull] K data)
|
|
{
|
|
return new ExchangeWebResult<K>(exchange, tradeMode, this.As<K>(data));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="tradeModes">Trade modes the result applies to</param>
|
|
/// <param name="data">The data</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode[]? tradeModes, [AllowNull] K data)
|
|
{
|
|
return new ExchangeWebResult<K>(exchange, tradeModes, this.As<K>(data));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="error">The error returned</param>
|
|
/// <returns></returns>
|
|
public WebCallResult<K> AsError<K>(Error error)
|
|
{
|
|
return new WebCallResult<K>(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, 0, null, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, ResultDataSource.Server, default, error);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString()
|
|
{
|
|
return (Success ? $"Success" : $"Error: {Error}") + $" in {ResponseTime}";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The result of a request
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
public class WebCallResult<T>: CallResult<T>
|
|
{
|
|
/// <summary>
|
|
/// The request http method
|
|
/// </summary>
|
|
public HttpMethod? RequestMethod { get; set; }
|
|
|
|
/// <summary>
|
|
/// HTTP protocol version
|
|
/// </summary>
|
|
public Version? HttpVersion { get; set; }
|
|
|
|
/// <summary>
|
|
/// The headers sent with the request
|
|
/// </summary>
|
|
public HttpRequestHeaders? RequestHeaders { get; set; }
|
|
|
|
/// <summary>
|
|
/// The request id
|
|
/// </summary>
|
|
public int? RequestId { get; set; }
|
|
|
|
/// <summary>
|
|
/// The url which was requested
|
|
/// </summary>
|
|
public string? RequestUrl { get; set; }
|
|
|
|
/// <summary>
|
|
/// The body of the request
|
|
/// </summary>
|
|
public string? RequestBody { get; set; }
|
|
|
|
/// <summary>
|
|
/// The status code of the response. Note that a OK status does not always indicate success, check the Success parameter for this.
|
|
/// </summary>
|
|
public HttpStatusCode? ResponseStatusCode { get; set; }
|
|
|
|
/// <summary>
|
|
/// Length in bytes of the response
|
|
/// </summary>
|
|
public long? ResponseLength { get; set; }
|
|
|
|
/// <summary>
|
|
/// The response headers
|
|
/// </summary>
|
|
public HttpResponseHeaders? ResponseHeaders { get; set; }
|
|
|
|
/// <summary>
|
|
/// The time between sending the request and receiving the response
|
|
/// </summary>
|
|
public TimeSpan? ResponseTime { get; set; }
|
|
|
|
/// <summary>
|
|
/// The data source of this result
|
|
/// </summary>
|
|
public ResultDataSource DataSource { get; set; } = ResultDataSource.Server;
|
|
|
|
/// <summary>
|
|
/// Create a new result
|
|
/// </summary>
|
|
public WebCallResult(
|
|
HttpStatusCode? code,
|
|
Version? httpVersion,
|
|
HttpResponseHeaders? responseHeaders,
|
|
TimeSpan? responseTime,
|
|
long? responseLength,
|
|
string? originalData,
|
|
int? requestId,
|
|
string? requestUrl,
|
|
string? requestBody,
|
|
HttpMethod? requestMethod,
|
|
HttpRequestHeaders? requestHeaders,
|
|
ResultDataSource dataSource,
|
|
[AllowNull] T data,
|
|
Error? error) : base(data, originalData, error)
|
|
{
|
|
HttpVersion = httpVersion;
|
|
ResponseStatusCode = code;
|
|
ResponseHeaders = responseHeaders;
|
|
ResponseTime = responseTime;
|
|
ResponseLength = responseLength;
|
|
|
|
RequestId = requestId;
|
|
RequestUrl = requestUrl;
|
|
RequestBody = requestBody;
|
|
RequestHeaders = requestHeaders;
|
|
RequestMethod = requestMethod;
|
|
DataSource = dataSource;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy as a dataless result
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public new WebCallResult AsDataless()
|
|
{
|
|
return new WebCallResult(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, Error);
|
|
}
|
|
/// <summary>
|
|
/// Copy as a dataless result
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public new WebCallResult AsDatalessError(Error error)
|
|
{
|
|
return new WebCallResult(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create a new error result
|
|
/// </summary>
|
|
/// <param name="error">The error</param>
|
|
public WebCallResult(Error? error) : this(null, null, null, null, null, null, null, null, null, null, null, ResultDataSource.Server, default, error) { }
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="data">The data of the new type</param>
|
|
/// <returns></returns>
|
|
public new WebCallResult<K> As<K>([AllowNull] K data)
|
|
{
|
|
return new WebCallResult<K>(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, Error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="error">The error returned</param>
|
|
/// <returns></returns>
|
|
public new WebCallResult<K> AsError<K>(Error error)
|
|
{
|
|
return new WebCallResult<K>(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, default, error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="data">The data</param>
|
|
/// <param name="error">The error returned</param>
|
|
/// <returns></returns>
|
|
public new WebCallResult<K> AsErrorWithData<K>(Error error, K data)
|
|
{
|
|
return new WebCallResult<K>(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, DataSource, data, error);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
|
|
/// </summary>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="tradeMode">Trade mode the result applies to</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<T> AsExchangeResult(string exchange, TradingMode tradeMode)
|
|
{
|
|
return new ExchangeWebResult<T>(exchange, tradeMode, this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
|
|
/// </summary>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="tradeModes">Trade modes the result applies to</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<T> AsExchangeResult(string exchange, TradingMode[] tradeModes)
|
|
{
|
|
return new ExchangeWebResult<T>(exchange, tradeModes, this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="tradeMode">Trade mode the result applies to</param>
|
|
/// <param name="data">Data</param>
|
|
/// <param name="nextPageToken">Next page token</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode tradeMode, [AllowNull] K data, INextPageToken? nextPageToken = null)
|
|
{
|
|
return new ExchangeWebResult<K>(exchange, tradeMode, As<K>(data), nextPageToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult of a new data type
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="tradeModes">Trade modes the result applies to</param>
|
|
/// <param name="data">Data</param>
|
|
/// <param name="nextPageToken">Next page token</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<K> AsExchangeResult<K>(string exchange, TradingMode[]? tradeModes, [AllowNull] K data, INextPageToken? nextPageToken = null)
|
|
{
|
|
return new ExchangeWebResult<K>(exchange, tradeModes, As<K>(data), nextPageToken);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy the WebCallResult to an ExchangeWebResult with a specific error
|
|
/// </summary>
|
|
/// <typeparam name="K">The new type</typeparam>
|
|
/// <param name="exchange">The exchange</param>
|
|
/// <param name="error">The error returned</param>
|
|
/// <returns></returns>
|
|
public ExchangeWebResult<K> AsExchangeError<K>(string exchange, Error error)
|
|
{
|
|
return new ExchangeWebResult<K>(exchange, null, AsError<K>(error));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return a copy of this result with data source set to cache
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal WebCallResult<T> Cached()
|
|
{
|
|
return new WebCallResult<T>(ResponseStatusCode, HttpVersion, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, ResultDataSource.Cache, Data, Error);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString()
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.Append(Success ? $"Success response" : $"Error response: {Error}");
|
|
if (ResponseLength != null)
|
|
sb.Append($", {ResponseLength} bytes");
|
|
if (ResponseTime != null)
|
|
sb.Append($", received in {Math.Round(ResponseTime?.TotalMilliseconds ?? 0)}ms");
|
|
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
}
|