From 7345b02e34f59942c0630fc890b04eb7ac0f0144 Mon Sep 17 00:00:00 2001
From: maurizuki <62178459+maurizuki@users.noreply.github.com>
Date: Mon, 6 Nov 2023 16:53:05 +0100
Subject: [PATCH] Update ExchangeRatesClient.cs
---
.../ExchangeRatesClient.cs | 146 +++++++-----------
1 file changed, 52 insertions(+), 94 deletions(-)
diff --git a/src/ECB.Data.ExchangeRates/ExchangeRatesClient.cs b/src/ECB.Data.ExchangeRates/ExchangeRatesClient.cs
index 3615bfe..f1fa84a 100644
--- a/src/ECB.Data.ExchangeRates/ExchangeRatesClient.cs
+++ b/src/ECB.Data.ExchangeRates/ExchangeRatesClient.cs
@@ -21,9 +21,6 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
-using System.Globalization;
-using System.Xml.Linq;
-
namespace ECB.Data.ExchangeRates;
///
@@ -32,6 +29,8 @@ namespace ECB.Data.ExchangeRates;
///
public class ExchangeRatesClient : HttpClient
{
+ private readonly IExchangeRatesParser _parser;
+
///
/// Initializes a new instance of the ExchangeRatesClient class using a
/// HttpClientHandler that is disposed when this instance is disposed.
@@ -69,27 +68,51 @@ public ExchangeRatesClient(HttpMessageHandler handler) : this(handler, true)
///
/// handler is null.
public ExchangeRatesClient(HttpMessageHandler handler, bool disposeHandler)
- : base(handler, disposeHandler)
+ : this(handler, disposeHandler, new ExchangeRatesParser())
{
- BaseAddress = new Uri("https://data-api.ecb.europa.eu/service/data/EXR/");
}
- ///
- /// Returns the latest available daily average exchange rates of a list of
- /// currencies.
- ///
- ///
- /// The list of the required currencies. Leave empty to get all the
- /// available currencies.
- ///
- ///
- /// A task that represents the asynchronous operation. The task result contains
- /// the latest available daily average exchange rates of a list of currencies.
- ///
- ///
- /// The response status code does not indicate success.
- ///
- public async Task> GetDailyAverageRatesAsync(params string[] currencies)
+ ///
+ /// Initializes a new instance of the ExchangeRatesClient class with the
+ /// provided handler, and specifies whether that handler should be disposed
+ /// when this instance is disposed.
+ ///
+ ///
+ /// The HttpMessageHandler responsible for processing the HTTP response
+ /// messages.
+ ///
+ ///
+ /// true if the inner handler should be disposed of by
+ /// ExchangeRatesClient.Dispose; false if you intend to reuse the inner
+ /// handler.
+ ///
+ /// handler is null or parser is null.
+ public ExchangeRatesClient(
+ HttpMessageHandler handler,
+ bool disposeHandler,
+ IExchangeRatesParser parser)
+ : base(handler, disposeHandler)
+ {
+ _parser = parser ?? throw new ArgumentNullException(nameof(parser));
+ BaseAddress = new Uri("https://data-api.ecb.europa.eu/service/data/EXR/");
+ }
+
+ ///
+ /// Returns the latest available daily average exchange rates of a list of
+ /// currencies.
+ ///
+ ///
+ /// The list of the required currencies. Leave empty to get all the
+ /// available currencies.
+ ///
+ ///
+ /// A task that represents the asynchronous operation. The task result contains
+ /// the latest available daily average exchange rates of a list of currencies.
+ ///
+ ///
+ /// The response status code does not indicate success.
+ ///
+ public async Task> GetDailyAverageRatesAsync(params string[] currencies)
{
return await GetExchangeRatesAsync(
string.Format(
@@ -118,7 +141,7 @@ public async Task> GetDailyAverageRatesAsync(params string[]
///
/// The response status code does not indicate success.
///
- public async Task> GetDailyAverageRatesAsync(DateTime date, params string[] currencies)
+ public async Task> GetDailyAverageRatesAsync(DateTime date, params string[] currencies)
{
return await GetDailyAverageRatesAsync(date, date, currencies);
}
@@ -143,7 +166,7 @@ public async Task> GetDailyAverageRatesAsync(DateTime date, p
///
/// The response status code does not indicate success.
///
- public async Task> GetDailyAverageRatesAsync(DateTime startDate, DateTime endDate, params string[] currencies)
+ public async Task> GetDailyAverageRatesAsync(DateTime startDate, DateTime endDate, params string[] currencies)
{
return await GetExchangeRatesAsync(
string.Format(
@@ -173,7 +196,7 @@ public async Task> GetDailyAverageRatesAsync(DateTime startDa
///
/// The response status code does not indicate success.
///
- public async Task> GetMonthlyAverageRatesAsync(int month, int year, params string[] currencies)
+ public async Task> GetMonthlyAverageRatesAsync(int month, int year, params string[] currencies)
{
return await GetMonthlyAverageRatesAsync(month, year, month, year, currencies);
}
@@ -204,7 +227,7 @@ public async Task> GetMonthlyAverageRatesAsync(int month, int
///
/// The response status code does not indicate success.
///
- public async Task> GetMonthlyAverageRatesAsync(int startMonth, int startYear, int endMonth, int endYear, params string[] currencies)
+ public async Task> GetMonthlyAverageRatesAsync(int startMonth, int startYear, int endMonth, int endYear, params string[] currencies)
{
return await GetExchangeRatesAsync(
string.Format(
@@ -233,7 +256,7 @@ public async Task> GetMonthlyAverageRatesAsync(int startMonth
///
/// The response status code does not indicate success.
///
- public async Task> GetAnnualAverageRatesAsync(int year, params string[] currencies)
+ public async Task> GetAnnualAverageRatesAsync(int year, params string[] currencies)
{
return await GetAnnualAverageRatesAsync(year, year, currencies);
}
@@ -258,7 +281,7 @@ public async Task> GetAnnualAverageRatesAsync(int year, param
///
/// The response status code does not indicate success.
///
- public async Task> GetAnnualAverageRatesAsync(int startYear, int endYear, params string[] currencies)
+ public async Task> GetAnnualAverageRatesAsync(int startYear, int endYear, params string[] currencies)
{
return await GetExchangeRatesAsync(
string.Format(
@@ -292,7 +315,7 @@ private static string Format(int year)
return $"{year:D4}";
}
- private async Task> GetExchangeRatesAsync(string requestUri)
+ private async Task> GetExchangeRatesAsync(string requestUri)
{
var response = await GetAsync(requestUri);
@@ -305,71 +328,6 @@ private async Task> GetExchangeRatesAsync(string requestUri)
);
}
- return Parse(await response.Content.ReadAsStringAsync());
- }
-
- private static List Parse(string xml)
- {
- if (string.IsNullOrWhiteSpace(xml)) return new List();
-
- var document = XDocument.Parse(xml);
-
- if (document.Root == null) return new List();
-
- var genericNamespace = document.Root.GetNamespaceOfPrefix("generic");
-
- if (genericNamespace == null) return new List();
-
- var seriesKeyValueName = XName.Get("Value", genericNamespace.NamespaceName);
- var obsName = XName.Get("Obs", genericNamespace.NamespaceName);
- var obsDimensionName = XName.Get("ObsDimension", genericNamespace.NamespaceName);
- var obsValueName = XName.Get("ObsValue", genericNamespace.NamespaceName);
-
- return document.Descendants(XName.Get("Series", genericNamespace.NamespaceName))
- .Select(
- a =>
- {
- var seriesKeyValues = a.Descendants(seriesKeyValueName)
- .ToDictionary(
- b => b.Attribute("id")!.Value,
- b => b.Attribute("value")?.Value
- );
- return new
- {
- Frequency =
- seriesKeyValues.GetValueOrDefault("FREQ"),
- Currency =
- seriesKeyValues.GetValueOrDefault("CURRENCY"),
- CurrencyDenominator =
- seriesKeyValues.GetValueOrDefault("CURRENCY_DENOM"),
- ExchangeRateType =
- seriesKeyValues.GetValueOrDefault("EXR_TYPE"),
- SeriesVariation =
- seriesKeyValues.GetValueOrDefault("EXR_SUFFIX"),
- Obs = a.Descendants(obsName),
- };
- }
- )
- .SelectMany(
- a => a.Obs,
- (a, b) => new ExchangeRate
- {
- Frequency = a.Frequency,
- Currency = a.Currency,
- CurrencyDenominator = a.CurrencyDenominator,
- ExchangeRateType = a.ExchangeRateType,
- SeriesVariation = a.SeriesVariation,
- TimePeriod = b.Descendants(obsDimensionName)
- .FirstOrDefault()?.Attribute("value")?.Value,
- Value = decimal.TryParse(
- b.Descendants(obsValueName)
- .FirstOrDefault()?.Attribute("value")?.Value ?? "0",
- CultureInfo.InvariantCulture,
- out var value
- )
- ? value
- : 0,
- }
- ).ToList();
+ return _parser.Parse(await response.Content.ReadAsStringAsync());
}
}