From a9d0fa57f2ace4078ccdb44b1bbf8292690306d7 Mon Sep 17 00:00:00 2001 From: Alex Shibalkin Date: Wed, 12 Feb 2025 15:14:14 +0500 Subject: [PATCH 1/7] =?UTF-8?q?=D0=9C=D0=B0=D0=BF=D0=BF=D0=B8=D0=BD=D0=B3?= =?UTF-8?q?=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=20=D0=BE=D1=82=20?= =?UTF-8?q?=D0=BA=D0=BB=D0=B8=D0=B5=D0=BD=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interfaces/ITimestampedValuesClient.cs | 22 +----- .../Clients/Mapping/ISetpointMappingClient.cs | 6 ++ .../Mapping/ITimestampedMappingClient.cs | 27 +++++++ .../Clients/Mapping/SetpointMappingClient.cs | 79 +++++++++++++++++++ .../Mapping/TimestampedMappingClient.cs | 65 +++++++++++++++ .../Clients/SetpointClient.cs | 35 +------- .../Clients/TimestampedValuesClient.cs | 27 +------ DD.Persistence.Client/DependencyInjection.cs | 13 ++- .../ISetpointConfigStorage.cs | 11 --- .../SetpointConfigStorage.cs | 20 ----- .../Controllers/SetpointControllerTest.cs | 4 +- 11 files changed, 197 insertions(+), 112 deletions(-) create mode 100644 DD.Persistence.Client/Clients/Mapping/ISetpointMappingClient.cs create mode 100644 DD.Persistence.Client/Clients/Mapping/ITimestampedMappingClient.cs create mode 100644 DD.Persistence.Client/Clients/Mapping/SetpointMappingClient.cs create mode 100644 DD.Persistence.Client/Clients/Mapping/TimestampedMappingClient.cs delete mode 100644 DD.Persistence.Client/ISetpointConfigStorage.cs delete mode 100644 DD.Persistence.Client/SetpointConfigStorage.cs diff --git a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs index 27449b2..04458f8 100644 --- a/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/ITimestampedValuesClient.cs @@ -35,16 +35,7 @@ public interface ITimestampedValuesClient : IDisposable int take, CancellationToken token); - /// - /// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен - /// - /// - /// - /// Фильтр свойств набора - /// - /// - /// - Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); + /// /// Получить данные, начиная с заданной отметки времени @@ -94,13 +85,6 @@ public interface ITimestampedValuesClient : IDisposable /// Task GetDatesRange(Guid discriminatorId, CancellationToken token); - /// - /// - /// - /// - /// - /// - /// - /// - Task> GetLast(Guid idDiscriminator, int take, CancellationToken token); + + } \ No newline at end of file diff --git a/DD.Persistence.Client/Clients/Mapping/ISetpointMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/ISetpointMappingClient.cs new file mode 100644 index 0000000..9d07475 --- /dev/null +++ b/DD.Persistence.Client/Clients/Mapping/ISetpointMappingClient.cs @@ -0,0 +1,6 @@ +using DD.Persistence.Client.Clients.Interfaces; + +namespace DD.Persistence.Client.Clients.Mapping; +public interface ISetpointMappingClient : ISetpointClient +{ +} diff --git a/DD.Persistence.Client/Clients/Mapping/ITimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/ITimestampedMappingClient.cs new file mode 100644 index 0000000..5076c5f --- /dev/null +++ b/DD.Persistence.Client/Clients/Mapping/ITimestampedMappingClient.cs @@ -0,0 +1,27 @@ +using DD.Persistence.Client.Clients.Interfaces; + +namespace DD.Persistence.Client.Clients.Mapping; +public interface ITimestampedMappingClient : ITimestampedValuesClient +{ + /// + /// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен + /// + /// + /// + /// Фильтр свойств набора + /// + /// + /// + Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); + + + /// + /// + /// + /// + /// + /// + /// + /// + Task> GetLast(Guid idDiscriminator, int take, CancellationToken token); +} diff --git a/DD.Persistence.Client/Clients/Mapping/SetpointMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/SetpointMappingClient.cs new file mode 100644 index 0000000..34a6b1e --- /dev/null +++ b/DD.Persistence.Client/Clients/Mapping/SetpointMappingClient.cs @@ -0,0 +1,79 @@ + +using DD.Persistence.Client.Clients.Interfaces; +using DD.Persistence.Models; +using DD.Persistence.Models.Common; +using System.Text.Json; + +namespace DD.Persistence.Client.Clients.Mapping; +internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary mappingConfigs) : ISetpointMappingClient +{ + public async Task Add(Guid setpointKey, object newValue, CancellationToken token) + => await setpointClient.Add(setpointKey, newValue, token); + + public void Dispose() + { + setpointClient.Dispose(); + } + + public async Task> GetCurrent(IEnumerable setpointKeys, CancellationToken token) + => (await setpointClient.GetCurrent(setpointKeys, token)) + .Select(x => new SetpointValueDto + { + Key = x.Key, + Value = DeserializeValue(x.Key, (JsonElement)x.Value) + }); + + public async Task> GetCurrentDictionary(IEnumerable setpointConfigs, CancellationToken token) + { + return (await setpointClient.GetCurrent(setpointConfigs, token)) + .ToDictionary(x => x.Key, x => DeserializeValue(x.Key, (JsonElement)x.Value)); + } + + public async Task GetDatesRangeAsync(CancellationToken token) + => await setpointClient.GetDatesRangeAsync(token); + + public async Task> GetHistory(IEnumerable setpointKeys, DateTimeOffset historyMoment, CancellationToken token) + { + var result = await setpointClient.GetHistory(setpointKeys, historyMoment, token); + + foreach (var dto in result) + dto.Value = DeserializeValue(dto.Key, (JsonElement)dto.Value); + + return result; + } + + public async Task>> GetLog(IEnumerable setpointKeys, CancellationToken token) + { + var result = await setpointClient.GetLog(setpointKeys, token); + + foreach (var item in result) + DeserializeList(result[item.Key]); + + return result; + } + + public async Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token) + { + var res = await setpointClient.GetPart(dateBegin, take, token); + + DeserializeList(res); + + return res; + } + + + + private object DeserializeValue(Guid key, JsonElement value) + { + if (mappingConfigs.TryGetValue(key, out var type)) + return value.Deserialize(type)!; + + return value; + } + private void DeserializeList(IEnumerable? result) + { + foreach (var log in result) + log.Value = DeserializeValue(log.Key, (JsonElement)log.Value); + + } +} diff --git a/DD.Persistence.Client/Clients/Mapping/TimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/TimestampedMappingClient.cs new file mode 100644 index 0000000..3effedb --- /dev/null +++ b/DD.Persistence.Client/Clients/Mapping/TimestampedMappingClient.cs @@ -0,0 +1,65 @@ +using DD.Persistence.Client.Clients.Interfaces; +using DD.Persistence.Models; +using DD.Persistence.Models.Common; +using System.Collections.Concurrent; + +namespace DD.Persistence.Client.Clients.Mapping; +internal class TimestampedMappingClient(ITimestampedValuesClient client) : ITimestampedMappingClient +{ + /// + private readonly ConcurrentDictionary mapperCache = new(); + + public async Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token) + => await client.AddRange(discriminatorId, dtos, token); + + public async Task Count(Guid discriminatorId, CancellationToken token) + => await client.Count(discriminatorId, token); + + public void Dispose() + { + client.Dispose(); + } + + /// + public async Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var data = await Get([discriminatorId], geTimestamp, columnNames, skip, take, token); + var mapper = GetMapper(discriminatorId); + + return data.Select(mapper.DeserializeTimeStampedData); + } + + /// + public async Task> GetLast(Guid idDiscriminator, int take, CancellationToken token) + { + var data = await GetLast(idDiscriminator, take, token); + var mapper = GetMapper(idDiscriminator); + + return data.Select(mapper.DeserializeTimeStampedData); + } + + + /// + private TimestampedSetMapper GetMapper(Guid idDiscriminator) + { + return (TimestampedSetMapper)mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator)); + } + + public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? timestampBegin, IEnumerable? columnNames, int skip, int take, CancellationToken token) + => await client.Get(discriminatorIds, timestampBegin, columnNames, skip, take, token); + + public async Task GetDatesRange(Guid discriminatorId, CancellationToken token) + => await client.GetDatesRange(discriminatorId, token); + + public async Task> GetFirst(Guid discriminatorId, int take, CancellationToken token) + => await client.GetFirst(discriminatorId, take, token); + + public async Task> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) + => await client.GetGtDate(discriminatorId, timestampBegin, token); + + public async Task> GetLast(Guid discriminatorId, int take, CancellationToken token) + => await client.GetLast(discriminatorId, take, token); + + public async Task> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default) + => await client.GetResampledData(discriminatorId, timestampBegin, intervalSec, approxPointsCount, token); +} diff --git a/DD.Persistence.Client/Clients/SetpointClient.cs b/DD.Persistence.Client/Clients/SetpointClient.cs index dfb5026..a2c401e 100644 --- a/DD.Persistence.Client/Clients/SetpointClient.cs +++ b/DD.Persistence.Client/Clients/SetpointClient.cs @@ -3,9 +3,6 @@ using DD.Persistence.Client.Clients.Base; using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Models; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Globalization; using DD.Persistence.Models.Common; namespace DD.Persistence.Client.Clients; @@ -13,15 +10,12 @@ namespace DD.Persistence.Client.Clients; public class SetpointClient : BaseClient, ISetpointClient { private readonly IRefitSetpointClient refitSetpointClient; - private readonly ISetpointConfigStorage setpointConfigStorage; public SetpointClient( IRefitClientFactory refitSetpointClientFactory, - ISetpointConfigStorage setpointConfigStorage, ILogger logger) : base(logger) { this.refitSetpointClient = refitSetpointClientFactory.Create(); - this.setpointConfigStorage = setpointConfigStorage; } public async Task> GetCurrent(IEnumerable setpointKeys, CancellationToken token) @@ -31,7 +25,7 @@ public class SetpointClient : BaseClient, ISetpointClient return result!.Select(x => new SetpointValueDto { Key = x.Key, - Value = DeserializeValue(x.Key, x.Value) + Value = x.Value }); } @@ -43,16 +37,13 @@ public class SetpointClient : BaseClient, ISetpointClient async () => await refitSetpointClient.GetCurrent(setpointConfigs, token), token); - return result!.ToDictionary(x => x.Key,x => DeserializeValue(x.Key,x.Value)); + return result!.ToDictionary(x => x.Key,x => (object)x.Value); } public async Task> GetHistory(IEnumerable setpointKeys, DateTimeOffset historyMoment, CancellationToken token) { var result = await ExecuteGetResponse( async () => await refitSetpointClient.GetHistory(setpointKeys, historyMoment, token), token); - - foreach(var dto in result) - dto.Value = DeserializeValue(dto.Key, (JsonElement)dto.Value); return result!; @@ -63,9 +54,6 @@ public class SetpointClient : BaseClient, ISetpointClient var result = await ExecuteGetResponse( async () => await refitSetpointClient.GetLog(setpointKeys, token), token); - foreach(var item in result) - DeserializeList(result[item.Key]); - return result!; } @@ -82,8 +70,6 @@ public class SetpointClient : BaseClient, ISetpointClient var result = await ExecuteGetResponse( async () => await refitSetpointClient.GetPart(dateBegin, take, token), token); - DeserializeList(result); - return result!; } @@ -101,21 +87,4 @@ public class SetpointClient : BaseClient, ISetpointClient GC.SuppressFinalize(this); } - - - private object DeserializeValue(Guid key, JsonElement value) - { - if (setpointConfigStorage.TryGetType(key, out var type)) - return value.Deserialize(type)!; - - return value; - } - private void DeserializeList(IEnumerable? result) - { - foreach (var log in result) - log.Value = DeserializeValue(log.Key, (JsonElement)log.Value); - - } - - } diff --git a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs index 123ed71..68e631f 100644 --- a/DD.Persistence.Client/Clients/TimestampedValuesClient.cs +++ b/DD.Persistence.Client/Clients/TimestampedValuesClient.cs @@ -19,8 +19,7 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient this.refitTimestampedSetClient = refitTimestampedSetClientFactory.Create(); } - /// - private readonly ConcurrentDictionary mapperCache = new(); + /// public async Task AddRange(Guid discriminatorId, IEnumerable sets, CancellationToken token) @@ -39,15 +38,6 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient return result!; } - /// - public async Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) - { - var data = await Get([discriminatorId], geTimestamp, columnNames, skip, take, token); - var mapper = GetMapper(discriminatorId); - - return data.Select(mapper.DeserializeTimeStampedData); - } - /// public async Task> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) { @@ -102,20 +92,7 @@ public class TimestampedValuesClient : BaseClient, ITimestampedValuesClient return result; } - /// - public async Task> GetLast(Guid idDiscriminator, int take, CancellationToken token) - { - var data = await GetLast(idDiscriminator, take, token); - var mapper = GetMapper(idDiscriminator); - - return data.Select(mapper.DeserializeTimeStampedData); - } - - /// - private TimestampedSetMapper GetMapper(Guid idDiscriminator) - { - return (TimestampedSetMapper)mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator)); - } + /// public void Dispose() diff --git a/DD.Persistence.Client/DependencyInjection.cs b/DD.Persistence.Client/DependencyInjection.cs index 89f65cf..771c6ea 100644 --- a/DD.Persistence.Client/DependencyInjection.cs +++ b/DD.Persistence.Client/DependencyInjection.cs @@ -1,5 +1,6 @@ using DD.Persistence.Client.Clients; using DD.Persistence.Client.Clients.Interfaces; +using DD.Persistence.Client.Clients.Mapping; using DD.Persistence.Models; using Microsoft.Extensions.DependencyInjection; @@ -25,10 +26,18 @@ public static class DependencyInjection services.AddTransient(); services.AddTransient(); - services.AddSingleton(provider => + return services; + } + + + public static IServiceCollection AddPersistenceMapping(this IServiceCollection services, Dictionary? mappingConfigs) + { + services.AddTransient(provider => { - return new SetpointConfigStorage(setpointTypeConfigs); + var client = provider.GetRequiredService(); + return new SetpointMappingClient(client, mappingConfigs); }); + services.AddTransient(); return services; } } diff --git a/DD.Persistence.Client/ISetpointConfigStorage.cs b/DD.Persistence.Client/ISetpointConfigStorage.cs deleted file mode 100644 index 2c73783..0000000 --- a/DD.Persistence.Client/ISetpointConfigStorage.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace DD.Persistence.Client; -public interface ISetpointConfigStorage -{ - bool TryGetType(Guid id, out Type type); -} diff --git a/DD.Persistence.Client/SetpointConfigStorage.cs b/DD.Persistence.Client/SetpointConfigStorage.cs deleted file mode 100644 index 5cfbabf..0000000 --- a/DD.Persistence.Client/SetpointConfigStorage.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace DD.Persistence.Client; -internal class SetpointConfigStorage : ISetpointConfigStorage -{ - private readonly Dictionary setpointTypeConfigs; - - public SetpointConfigStorage(Dictionary? setpointTypeConfigs) - { - this.setpointTypeConfigs = setpointTypeConfigs?? new Dictionary(); - } - - public bool TryGetType(Guid id, out Type type) - { - return setpointTypeConfigs.TryGetValue(id, out type); - } - - public void AddOrReplace(Guid id, Type type) - { - setpointTypeConfigs[id] = type; - } -} diff --git a/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs index 64506dc..48b6ab0 100644 --- a/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs @@ -13,7 +13,7 @@ namespace DD.Persistence.IntegrationTests.Controllers public class SetpointControllerTest : BaseIntegrationTest { private readonly ISetpointClient setpointClient; - private readonly SetpointConfigStorage configStorage; + private readonly MappingConfigStorage configStorage; public SetpointControllerTest(WebAppFactoryFixture factory) : base(factory) { var refitClientFactory = scope.ServiceProvider @@ -23,7 +23,7 @@ namespace DD.Persistence.IntegrationTests.Controllers setpointClient = scope.ServiceProvider .GetRequiredService(); - configStorage = (SetpointConfigStorage)scope.ServiceProvider.GetRequiredService(); + configStorage = (MappingConfigStorage)scope.ServiceProvider.GetRequiredService(); } From 77fa9d2c46fa06c7402b613a57fca5282d2be178 Mon Sep 17 00:00:00 2001 From: Alex Shibalkin Date: Wed, 12 Feb 2025 16:17:13 +0500 Subject: [PATCH 2/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/SetpointControllerTest.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs index 48b6ab0..55cbba6 100644 --- a/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs @@ -2,6 +2,7 @@ using DD.Persistence.Client; using DD.Persistence.Client.Clients; using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces.Refit; +using DD.Persistence.Client.Clients.Mapping; using DD.Persistence.Database.Entity; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -13,17 +14,14 @@ namespace DD.Persistence.IntegrationTests.Controllers public class SetpointControllerTest : BaseIntegrationTest { private readonly ISetpointClient setpointClient; - private readonly MappingConfigStorage configStorage; public SetpointControllerTest(WebAppFactoryFixture factory) : base(factory) { var refitClientFactory = scope.ServiceProvider .GetRequiredService>(); - var logger = scope.ServiceProvider.GetRequiredService>(); setpointClient = scope.ServiceProvider .GetRequiredService(); - configStorage = (MappingConfigStorage)scope.ServiceProvider.GetRequiredService(); } @@ -32,12 +30,16 @@ namespace DD.Persistence.IntegrationTests.Controllers { var id = Guid.Parse("e0fcad22-1761-476e-a729-a3c59d51ba41"); - configStorage.AddOrReplace(id, typeof(float)); + var config = new Dictionary(); + config[id] = typeof(float); + + var setpointMapper = new SetpointMappingClient(setpointClient, config); + await setpointClient.Add(id, 48.3f, CancellationToken.None); //act - var response = await setpointClient.GetCurrent([id], CancellationToken.None); + var response = await setpointMapper.GetCurrent([id], CancellationToken.None); //assert Assert.NotNull(response); From c4b9878105be1c85dc3556de14ff70c334f0ca7f Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Fri, 14 Feb 2025 17:13:46 +0500 Subject: [PATCH 3/7] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D1=82=D0=B5=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Clients/TimestampedMappingClient.cs | 2 +- .../DD.Persistence.Test.csproj | 1 + DD.Persistence.Test/MappingClientsTest.cs | 40 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 DD.Persistence.Test/MappingClientsTest.cs diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs index 8211fd0..d9ada9c 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs @@ -6,7 +6,7 @@ using System.Collections.Concurrent; using System.Reflection; namespace DD.Persistence.Client.Clients.Mapping.Clients; -internal class TimestampedMappingClient(ITimestampedValuesClient client, Dictionary? mappingConfigs) : ITimestampedMappingClient +public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionary? mappingConfigs) : ITimestampedMappingClient { /// private readonly ConcurrentDictionary mapperCache = new(); diff --git a/DD.Persistence.Test/DD.Persistence.Test.csproj b/DD.Persistence.Test/DD.Persistence.Test.csproj index f71b186..43f350d 100644 --- a/DD.Persistence.Test/DD.Persistence.Test.csproj +++ b/DD.Persistence.Test/DD.Persistence.Test.csproj @@ -16,6 +16,7 @@ + diff --git a/DD.Persistence.Test/MappingClientsTest.cs b/DD.Persistence.Test/MappingClientsTest.cs new file mode 100644 index 0000000..967ce45 --- /dev/null +++ b/DD.Persistence.Test/MappingClientsTest.cs @@ -0,0 +1,40 @@ +using DD.Persistence.Client.Clients.Interfaces; +using DD.Persistence.Client.Clients.Mapping.Abstractions; +using DD.Persistence.Client.Clients.Mapping.Clients; +using DD.Persistence.Repositories; +using DD.Persistence.Services.Interfaces; +using NSubstitute; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DD.Persistence.Test; +public class MappingClientsTest +{ + private readonly ITimestampedValuesClient timestampedValuesClient = Substitute.For(); + private readonly TimestampedMappingClient timestampedMappingClient; + public record TestDto + { + public int Id { get; set; } + public string? Value { get; set; } + } + + private readonly Dictionary mappingConfigs = new Dictionary() + { + { Guid.NewGuid(), typeof(TestDto) } + }; + + public MappingClientsTest() + { + timestampedMappingClient = new TimestampedMappingClient(timestampedValuesClient, mappingConfigs); + } + + [Fact] + public async void Test() + { + var discriminatorIds = mappingConfigs.Keys; + var result = await timestampedMappingClient.Gett(discriminatorIds, null, null, null, 0, 1, CancellationToken.None); + } +} From efd7a7e639c7a609547d3c680946343821ad0ff8 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 24 Feb 2025 15:21:02 +0500 Subject: [PATCH 4/7] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BC=D0=BD=D0=BE=D0=B6=D0=B5=D1=81=D1=82=D0=B2=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=20=D1=81=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82=D0=B5=D0=B9?= =?UTF-8?q?=20=D0=B2=20TimeStampedClient?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Abstractions/ITimestampedMappingClient.cs | 24 ++- .../Mapping/Clients/SetpointMappingClient.cs | 40 +++-- .../Clients/TimestampedMappingClient.cs | 166 +++++++++++------- .../Clients/Mapping/TimestampedSetMapper.cs | 62 +++---- DD.Persistence.Models/TimestampedValuesDto.cs | 5 + DD.Persistence.Test/MappingClientsTest.cs | 77 ++++++-- .../Services/TimestampedValuesService.cs | 1 + 7 files changed, 232 insertions(+), 143 deletions(-) diff --git a/DD.Persistence.Client/Clients/Mapping/Abstractions/ITimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Abstractions/ITimestampedMappingClient.cs index 29908ff..6be0e58 100644 --- a/DD.Persistence.Client/Clients/Mapping/Abstractions/ITimestampedMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Abstractions/ITimestampedMappingClient.cs @@ -3,12 +3,12 @@ namespace DD.Persistence.Client.Clients.Mapping.Abstractions; /// -/// +/// Маппинг - обертка для клиента по работе с данными /// public interface ITimestampedMappingClient : ITimestampedValuesClient { /// - /// Получить данные с фильтрацией для нескольких систем. Значение фильтра null - отключен + /// Получить данные с преобразованием к заданному типу /// /// /// @@ -17,17 +17,29 @@ public interface ITimestampedMappingClient : ITimestampedValuesClient /// /// /// - Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token); - Task> Gett(IEnumerable discriminatorIds, string? filterTree, DateTimeOffset? timestampBegin, IEnumerable? columnNames, int skip, int take, CancellationToken token); + Task> GetMapped(Guid discriminatorId, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token); + + /// + /// Получить набор данных, преобразованных к соответствующим типам из заданного конфига + /// + /// + /// + /// + /// + /// + /// + /// + /// + Task>> GetMultiMapped(IEnumerable discriminatorIds, DateTimeOffset? timestampBegin, string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token); /// - /// + /// Получить данные с конца с преобразованием к заданному типу /// /// /// /// /// /// - Task> GetLast(Guid idDiscriminator, int take, CancellationToken token); + Task> GetLastMapped(Guid idDiscriminator, int take, CancellationToken token); } diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs index fed7187..010d2c0 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs @@ -5,16 +5,11 @@ using DD.Persistence.Models.Common; using System.Text.Json; namespace DD.Persistence.Client.Clients.Mapping.Clients; -internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary mappingConfigs) : ISetpointMappingClient + +/// +public class SetpointMappingClient(ISetpointClient setpointClient, Dictionary mappingConfigs) : ISetpointMappingClient { - public async Task Add(Guid setpointKey, object newValue, CancellationToken token) - => await setpointClient.Add(setpointKey, newValue, token); - - public void Dispose() - { - setpointClient.Dispose(); - } - + /// public async Task> GetCurrent(IEnumerable setpointKeys, CancellationToken token) => (await setpointClient.GetCurrent(setpointKeys, token)) .Select(x => new SetpointValueDto @@ -23,15 +18,16 @@ internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary< Value = DeserializeValue(x.Key, (JsonElement)x.Value) }); + /// public async Task> GetCurrentDictionary(IEnumerable setpointConfigs, CancellationToken token) { - return (await setpointClient.GetCurrent(setpointConfigs, token)) + var result = (await setpointClient.GetCurrent(setpointConfigs, token)) .ToDictionary(x => x.Key, x => DeserializeValue(x.Key, (JsonElement)x.Value)); + + return result; } - public async Task GetDatesRangeAsync(CancellationToken token) - => await setpointClient.GetDatesRangeAsync(token); - + /// public async Task> GetHistory(IEnumerable setpointKeys, DateTimeOffset historyMoment, CancellationToken token) { var result = await setpointClient.GetHistory(setpointKeys, historyMoment, token); @@ -42,6 +38,7 @@ internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary< return result; } + /// public async Task>> GetLog(IEnumerable setpointKeys, CancellationToken token) { var result = await setpointClient.GetLog(setpointKeys, token); @@ -52,6 +49,7 @@ internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary< return result; } + /// public async Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token) { var res = await setpointClient.GetPart(dateBegin, take, token); @@ -61,7 +59,19 @@ internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary< return res; } + /// + public async Task Add(Guid setpointKey, object newValue, CancellationToken token) + => await setpointClient.Add(setpointKey, newValue, token); + /// + public async Task GetDatesRangeAsync(CancellationToken token) + => await setpointClient.GetDatesRangeAsync(token); + + /// + public void Dispose() + { + setpointClient.Dispose(); + } private object DeserializeValue(Guid key, JsonElement value) { @@ -72,8 +82,10 @@ internal class SetpointMappingClient(ISetpointClient setpointClient, Dictionary< } private void DeserializeList(IEnumerable? result) { + if (result is null) + return; + foreach (var log in result) log.Value = DeserializeValue(log.Key, (JsonElement)log.Value); - } } diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs index d9ada9c..4a7a87b 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs @@ -3,93 +3,123 @@ using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Models; using DD.Persistence.Models.Common; using System.Collections.Concurrent; -using System.Reflection; namespace DD.Persistence.Client.Clients.Mapping.Clients; + +/// public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionary? mappingConfigs) : ITimestampedMappingClient { - /// - private readonly ConcurrentDictionary mapperCache = new(); + private readonly ConcurrentDictionary mapperCache = new(); + /// + public async Task> GetMapped(Guid discriminatorId, DateTimeOffset? geTimestamp, + string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var data = await Get([discriminatorId], geTimestamp, filterTree, columnNames, skip, take, token); + var mapper = GetMapper(discriminatorId); + + var mappedDtos = data.Select(mapper.DeserializeTimeStampedData).OfType(); + + return mappedDtos; + } + + /// + public async Task> GetLastMapped(Guid idDiscriminator, int take, CancellationToken token) + { + var data = await GetLast(idDiscriminator, take, token); + var mapper = GetMapper(idDiscriminator); + + var mappedDtos = data.Select(mapper.DeserializeTimeStampedData).OfType(); + + return mappedDtos; + } + + /// + public async Task>> GetMultiMapped(IEnumerable discriminatorIds, DateTimeOffset? geTimestamp, + string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var data = await client.Get(discriminatorIds, geTimestamp, filterTree, columnNames, skip, take, token); + + var result = discriminatorIds + .ToDictionary(discriminatorId => discriminatorId, discriminatorId => + { + if (mappingConfigs is null) + throw new ArgumentNullException(nameof(mappingConfigs)); + + if (!mappingConfigs.TryGetValue(discriminatorId, out var type)) + throw new InvalidCastException(); + + var mapper = GetMapper(discriminatorId, type); + + var mappedDtos = data + .Where(e => e.DiscriminatorId == discriminatorId) + .Select(mapper.DeserializeTimeStampedData); + + return mappedDtos; + }); + + //var genericMapperType = typeof(TimestampedSetMapper<>).MakeGenericType(type); + + //var ttype = typeof(TimestampedSetMapper); + //object b = 0; + + //var mapper = MapperMethodInfo + // .MakeGenericMethod([type]) + // .Invoke(this, [discriminatorId]); + + //var deserializeMethod = genericMapperType + // .GetMethod(nameof(TimestampedSetMapper.DeserializeTimeStampedData))!; + // ToDo: приводим к Dictionary + + return result; + } + + /// public async Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token) => await client.AddRange(discriminatorId, dtos, token); + /// public async Task Count(Guid discriminatorId, CancellationToken token) => await client.Count(discriminatorId, token); + /// + public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? timestampBegin, + string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token) + => await client.Get(discriminatorIds, timestampBegin, filterTree, columnNames, skip, take, token); + + /// + public async Task GetDatesRange(Guid discriminatorId, CancellationToken token) + => await client.GetDatesRange(discriminatorId, token); + + /// + public async Task> GetFirst(Guid discriminatorId, int take, CancellationToken token) + => await client.GetFirst(discriminatorId, take, token); + + /// + public async Task> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) + => await client.GetGtDate(discriminatorId, timestampBegin, token); + + /// + public async Task> GetLast(Guid discriminatorId, int take, CancellationToken token) + => await client.GetLast(discriminatorId, take, token); + + /// + public async Task> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default) + => await client.GetResampledData(discriminatorId, timestampBegin, intervalSec, approxPointsCount, token); + + /// public void Dispose() { client.Dispose(); } - /// - public async Task> Get(Guid discriminatorId, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token) + private TimestampedSetMapper GetMapper(Guid idDiscriminator, Type type) { - var data = await Get([discriminatorId], geTimestamp, filterTree, columnNames, skip, take, token); - var mapper = GetMapper(discriminatorId); - - return data.Select(mapper.DeserializeTimeStampedData); + return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type)); } - /// - public async Task> GetLast(Guid idDiscriminator, int take, CancellationToken token) + private TimestampedSetMapper GetMapper(Guid idDiscriminator) { - var data = await GetLast(idDiscriminator, take, token); - var mapper = GetMapper(idDiscriminator); - - return data.Select(mapper.DeserializeTimeStampedData); + return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T))); } - - public async Task> Gett(IEnumerable discriminatorIds, string? filterTree, DateTimeOffset? timestampBegin, IEnumerable? columnNames, int skip, int take, CancellationToken token) - { - var data = await client.Get(discriminatorIds, timestampBegin, filterTree, columnNames, skip, take, token); - - // ToDo: рефакторинг - foreach (var discriminatorId in discriminatorIds) - { - if (mappingConfigs.TryGetValue(discriminatorId, out var type)) - { - var genericType = typeof(TimestampedSetMapper<>).MakeGenericType(type); - - var mapper = - typeof(TimestampedMappingClient) - .GetMethod(nameof(GetMapper))! - .MakeGenericMethod([type]) - .Invoke(this, [discriminatorId]); - var mapperInstance = Activator.CreateInstance(genericType, mapper); // ToDo: возможно не нужно - - var deserializeMethod = genericType - .GetMethod("DeserializeTimeStampedData")!; - - var d = data.Select(e => deserializeMethod.Invoke(mapperInstance, [e])); - // ToDo: приводим к Dictionary - } - } - - return new Dictionary(); - } - - /// - private TimestampedSetMapper GetMapper(Guid idDiscriminator) - { - return (TimestampedSetMapper)mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator)); - } - - public async Task> Get(IEnumerable discriminatorIds, DateTimeOffset? timestampBegin, string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token) - => await client.Get(discriminatorIds, timestampBegin, filterTree, columnNames, skip, take, token); - - public async Task GetDatesRange(Guid discriminatorId, CancellationToken token) - => await client.GetDatesRange(discriminatorId, token); - - public async Task> GetFirst(Guid discriminatorId, int take, CancellationToken token) - => await client.GetFirst(discriminatorId, take, token); - - public async Task> GetGtDate(Guid discriminatorId, DateTimeOffset timestampBegin, CancellationToken token) - => await client.GetGtDate(discriminatorId, timestampBegin, token); - - public async Task> GetLast(Guid discriminatorId, int take, CancellationToken token) - => await client.GetLast(discriminatorId, take, token); - - public async Task> GetResampledData(Guid discriminatorId, DateTimeOffset timestampBegin, double intervalSec = 600, int approxPointsCount = 1024, CancellationToken token = default) - => await client.GetResampledData(discriminatorId, timestampBegin, intervalSec, approxPointsCount, token); } diff --git a/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs b/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs index 4e88602..1911d09 100644 --- a/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs +++ b/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs @@ -6,60 +6,53 @@ using System.Text.Json; namespace DD.Persistence.Client.Clients.Mapping; -internal abstract class TimestampedSetMapperBase +internal class TimestampedSetMapper { - public abstract object Map(TimestampedValuesDto data); - -} -internal class TimestampedSetMapper : TimestampedSetMapperBase -{ - private readonly Type entityType = typeof(T); + private readonly Type entityType; public Guid IdDiscriminator { get; } private readonly ConcurrentDictionary PropertyCache = new(); - public TimestampedSetMapper(Guid idDiscriminator) + public TimestampedSetMapper(Guid idDiscriminator, Type entityType) { IdDiscriminator = idDiscriminator; + this.entityType = entityType; } - public override object Map(TimestampedValuesDto data) + public object DeserializeTimeStampedData(TimestampedValuesDto data) { - return DeserializeTimeStampedData(data)!; - } - - public T DeserializeTimeStampedData(TimestampedValuesDto data) - { - if (entityType.IsValueType) return MapStruct(data); - else - return MapClass(data); + + return MapClass(data); } - private T MapClass(TimestampedValuesDto data) + private object MapClass(TimestampedValuesDto data) { - var entity = (T)RuntimeHelpers.GetUninitializedObject(typeof(T)); + var entity = RuntimeHelpers.GetUninitializedObject(entityType); foreach (var (propertyName, value) in data.Values) { if (value is JsonElement jsonElement) SetPropertyValueFromJson(ref entity, propertyName, jsonElement); } - SetPropertyValue(ref entity, "Timestamp", data.Timestamp); + SetPropertyValue(ref entity, nameof(TimestampedValuesDto.Timestamp), data.Timestamp); + SetPropertyValue(ref entity, nameof(TimestampedValuesDto.DiscriminatorId), data.DiscriminatorId); + return entity; } - private T MapStruct(TimestampedValuesDto data) + private object MapStruct(TimestampedValuesDto data) { - var entity = Activator.CreateInstance(); + var entity = Activator.CreateInstance(entityType); object boxedEntity = entity!; foreach (var (propertyName, value) in data.Values) { if (value is JsonElement jsonElement) SetPropertyValueForStructFromJson(ref boxedEntity, propertyName, jsonElement); } - SetPropertyValueForStruct(ref boxedEntity, "Timestamp", data.Timestamp); + SetPropertyValueForStruct(ref boxedEntity, nameof(TimestampedValuesDto.Timestamp), data.Timestamp); + SetPropertyValueForStruct(ref boxedEntity, nameof(TimestampedValuesDto.DiscriminatorId), data.DiscriminatorId); - return (T)boxedEntity; + return boxedEntity; } private void SetPropertyValueForStructFromJson(ref object entity, string propertyName, JsonElement element) @@ -73,9 +66,7 @@ internal class TimestampedSetMapper : TimestampedSetMapperBase var value = element.Deserialize(property.PropertyType); property.SetValue(entity, value); } - catch (Exception ex) - { - } + catch (Exception) { } } private void SetPropertyValueForStruct(ref object entity, string propertyName, object value) { @@ -88,13 +79,11 @@ internal class TimestampedSetMapper : TimestampedSetMapperBase var convertedValue = Convert.ChangeType(value, property.PropertyType); property.SetValue(entity, convertedValue); } - catch (Exception ex) - { - } + catch (Exception) { } } - private void SetPropertyValueFromJson(ref T entity, string propertyName, JsonElement jsonElement) + private void SetPropertyValueFromJson(ref object entity, string propertyName, JsonElement jsonElement) { var property = GetPropertyInfo(propertyName); @@ -106,13 +95,10 @@ internal class TimestampedSetMapper : TimestampedSetMapperBase var value = jsonElement.Deserialize(property.PropertyType); property.SetValue(entity, value); } - catch (Exception ex) - { - - } + catch (Exception) { } } - private void SetPropertyValue(ref T entity, string propertyName, object value) + private void SetPropertyValue(ref object entity, string propertyName, object value) { var property = GetPropertyInfo(propertyName); if (property is null) @@ -123,9 +109,7 @@ internal class TimestampedSetMapper : TimestampedSetMapperBase var convertedValue = Convert.ChangeType(value, property.PropertyType); property.SetValue(entity, convertedValue); } - catch (Exception ex) - { - } + catch (Exception) { } } private PropertyInfo? GetPropertyInfo(string propertyName) diff --git a/DD.Persistence.Models/TimestampedValuesDto.cs b/DD.Persistence.Models/TimestampedValuesDto.cs index 13b592e..dbb04f9 100644 --- a/DD.Persistence.Models/TimestampedValuesDto.cs +++ b/DD.Persistence.Models/TimestampedValuesDto.cs @@ -7,6 +7,11 @@ namespace DD.Persistence.Models; /// public class TimestampedValuesDto : ITimestampAbstractDto { + /// + /// Дискриминатор + /// + public Guid DiscriminatorId { get; set; } + /// /// Временная отметка /// diff --git a/DD.Persistence.Test/MappingClientsTest.cs b/DD.Persistence.Test/MappingClientsTest.cs index 967ce45..fac46e4 100644 --- a/DD.Persistence.Test/MappingClientsTest.cs +++ b/DD.Persistence.Test/MappingClientsTest.cs @@ -1,29 +1,24 @@ using DD.Persistence.Client.Clients.Interfaces; -using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Client.Clients.Mapping.Clients; -using DD.Persistence.Repositories; -using DD.Persistence.Services.Interfaces; +using DD.Persistence.Models; using NSubstitute; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Text.Json; namespace DD.Persistence.Test; + +public record FirstTestDto(Guid DiscriminatorId, DateTimeOffset Timestamp, int Id, string? Value); + +public record SecondTestDto(Guid DiscriminatorId, DateTimeOffset Timestamp, int Id, double Capacity); + public class MappingClientsTest { private readonly ITimestampedValuesClient timestampedValuesClient = Substitute.For(); private readonly TimestampedMappingClient timestampedMappingClient; - public record TestDto - { - public int Id { get; set; } - public string? Value { get; set; } - } private readonly Dictionary mappingConfigs = new Dictionary() { - { Guid.NewGuid(), typeof(TestDto) } + { Guid.NewGuid(), typeof(FirstTestDto) }, + { Guid.NewGuid(), typeof(SecondTestDto) } }; public MappingClientsTest() @@ -32,9 +27,59 @@ public class MappingClientsTest } [Fact] - public async void Test() + public async Task GetMultiMapped() { + // Arrange var discriminatorIds = mappingConfigs.Keys; - var result = await timestampedMappingClient.Gett(discriminatorIds, null, null, null, 0, 1, CancellationToken.None); + var firstDiscriminatorId = discriminatorIds.First(); + var secondDiscriminatorId = discriminatorIds.Last(); + var getResult = new[] + { + new TimestampedValuesDto() + { + DiscriminatorId = firstDiscriminatorId, + Timestamp = DateTime.UtcNow, + Values = new Dictionary + { + { nameof(FirstTestDto.Id), JsonDocument.Parse(JsonSerializer.Serialize(1)).RootElement }, + { nameof(FirstTestDto.Value), JsonDocument.Parse(JsonSerializer.Serialize("string1")).RootElement} + } + }, + new TimestampedValuesDto() + { + DiscriminatorId = secondDiscriminatorId, + Timestamp = DateTime.UtcNow, + Values = new Dictionary + { + { nameof(SecondTestDto.Id), JsonDocument.Parse(JsonSerializer.Serialize(1)).RootElement }, + { nameof(SecondTestDto.Capacity), JsonDocument.Parse(JsonSerializer.Serialize(0.1)).RootElement} + } + } + }; + timestampedValuesClient + .Get(discriminatorIds, null, null, null, 0, 1, CancellationToken.None) + .ReturnsForAnyArgs(getResult); + + // Act + var result = await timestampedMappingClient.GetMultiMapped(discriminatorIds, null, null, null, 0, 1, CancellationToken.None); + + // Assert + Assert.NotNull(result); + Assert.NotEmpty(result); + Assert.Equal(getResult.Count(), result.Count()); + + var firstActualDto = (FirstTestDto) result[firstDiscriminatorId].First(); + Assert.NotNull(firstActualDto); + + var actualId = firstActualDto.Id.ToString(); + var expectedId = getResult[0].Values[nameof(FirstTestDto.Id)].ToString(); + Assert.Equal(expectedId, actualId); + + var secondActualDto = (SecondTestDto) result[secondDiscriminatorId].First(); + Assert.NotNull(secondActualDto); + + actualId = secondActualDto.Id.ToString(); + expectedId = getResult[1].Values[nameof(SecondTestDto.Id)].ToString(); + Assert.Equal(expectedId, actualId); } } diff --git a/DD.Persistence/Services/TimestampedValuesService.cs b/DD.Persistence/Services/TimestampedValuesService.cs index f18bcd9..d94b9f4 100644 --- a/DD.Persistence/Services/TimestampedValuesService.cs +++ b/DD.Persistence/Services/TimestampedValuesService.cs @@ -122,6 +122,7 @@ public class TimestampedValuesService : ITimestampedValuesService { var dto = new TimestampedValuesDto() { + DiscriminatorId = keyValuePair.Key, Timestamp = Timestamp.ToUniversalTime(), Values = dataScheme .ToDictionary(k => k.PropertyName, v => Values[v.Index]) From d2c4db015b0b687e3f0e9aff91ca9a465a6c0e5f Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Mon, 24 Feb 2025 15:56:16 +0500 Subject: [PATCH 5/7] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B5=D0=BA=D1=82=D0=B0=20=D1=81=20=D0=BC=D0=BE=D0=B4?= =?UTF-8?q?=D1=83=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC=D0=B8=20=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.Test/DD.Persistence.Test.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/DD.Persistence.Test/DD.Persistence.Test.csproj b/DD.Persistence.Test/DD.Persistence.Test.csproj index a7a5754..7006f98 100644 --- a/DD.Persistence.Test/DD.Persistence.Test.csproj +++ b/DD.Persistence.Test/DD.Persistence.Test.csproj @@ -16,6 +16,7 @@ + From 2dca1cc722fea478b31ecabfd180cf25953e7ec2 Mon Sep 17 00:00:00 2001 From: Alex Shibalkin Date: Thu, 27 Feb 2025 14:01:31 +0500 Subject: [PATCH 6/7] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Mapping/Abstractions/IMapperStorage.cs | 6 +++ .../Mapping/Clients/SetpointMappingClient.cs | 12 ++++- .../Clients/TimestampedMappingClient.cs | 49 ++++++------------- .../Clients/Mapping/MapperStorage.cs | 29 +++++++++++ DD.Persistence.Client/DependencyInjection.cs | 21 ++++---- .../Controllers/SetpointControllerTest.cs | 3 +- .../Configurations/MappingConfig.cs | 4 ++ DD.Persistence.Test/MappingClientsTest.cs | 24 ++++++--- Directory.Build.props | 3 ++ 9 files changed, 97 insertions(+), 54 deletions(-) create mode 100644 DD.Persistence.Client/Clients/Mapping/Abstractions/IMapperStorage.cs create mode 100644 DD.Persistence.Client/Clients/Mapping/MapperStorage.cs create mode 100644 DD.Persistence.Models/Configurations/MappingConfig.cs diff --git a/DD.Persistence.Client/Clients/Mapping/Abstractions/IMapperStorage.cs b/DD.Persistence.Client/Clients/Mapping/Abstractions/IMapperStorage.cs new file mode 100644 index 0000000..dd08e76 --- /dev/null +++ b/DD.Persistence.Client/Clients/Mapping/Abstractions/IMapperStorage.cs @@ -0,0 +1,6 @@ +namespace DD.Persistence.Client.Clients.Mapping.Abstractions; +internal interface IMapperStorage +{ + TimestampedSetMapper GetMapper(Guid idDiscriminator); + TimestampedSetMapper? GetMapper(Guid idDiscriminator); +} diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs index 010d2c0..a090d4d 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs @@ -2,13 +2,23 @@ using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Models; using DD.Persistence.Models.Common; +using DD.Persistence.Models.Configurations; using System.Text.Json; namespace DD.Persistence.Client.Clients.Mapping.Clients; /// -public class SetpointMappingClient(ISetpointClient setpointClient, Dictionary mappingConfigs) : ISetpointMappingClient +public class SetpointMappingClient : ISetpointMappingClient { + private readonly ISetpointClient setpointClient; + private readonly MappingConfig mappingConfigs; + + public SetpointMappingClient(ISetpointClient setpointClient, MappingConfig mappingConfigs) + { + this.setpointClient = setpointClient; + this.mappingConfigs = mappingConfigs; + } + /// public async Task> GetCurrent(IEnumerable setpointKeys, CancellationToken token) => (await setpointClient.GetCurrent(setpointKeys, token)) diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs index 4a7a87b..0d73376 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs @@ -2,21 +2,27 @@ using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Models; using DD.Persistence.Models.Common; -using System.Collections.Concurrent; namespace DD.Persistence.Client.Clients.Mapping.Clients; /// -public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionary? mappingConfigs) : ITimestampedMappingClient +internal class TimestampedMappingClient : ITimestampedMappingClient { - private readonly ConcurrentDictionary mapperCache = new(); + private readonly ITimestampedValuesClient client; + private readonly IMapperStorage mapperStorage; + + public TimestampedMappingClient(ITimestampedValuesClient client, IMapperStorage mapperStorage) + { + this.client = client; + this.mapperStorage = mapperStorage; + } /// public async Task> GetMapped(Guid discriminatorId, DateTimeOffset? geTimestamp, string? filterTree, IEnumerable? columnNames, int skip, int take, CancellationToken token) { var data = await Get([discriminatorId], geTimestamp, filterTree, columnNames, skip, take, token); - var mapper = GetMapper(discriminatorId); + var mapper = mapperStorage.GetMapper(discriminatorId); var mappedDtos = data.Select(mapper.DeserializeTimeStampedData).OfType(); @@ -27,7 +33,7 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar public async Task> GetLastMapped(Guid idDiscriminator, int take, CancellationToken token) { var data = await GetLast(idDiscriminator, take, token); - var mapper = GetMapper(idDiscriminator); + var mapper = mapperStorage.GetMapper(idDiscriminator); var mappedDtos = data.Select(mapper.DeserializeTimeStampedData).OfType(); @@ -43,14 +49,10 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar var result = discriminatorIds .ToDictionary(discriminatorId => discriminatorId, discriminatorId => { - if (mappingConfigs is null) - throw new ArgumentNullException(nameof(mappingConfigs)); - - if (!mappingConfigs.TryGetValue(discriminatorId, out var type)) - throw new InvalidCastException(); - - var mapper = GetMapper(discriminatorId, type); + var mapper = mapperStorage.GetMapper(discriminatorId); + ArgumentNullException.ThrowIfNull(mapper); + var mappedDtos = data .Where(e => e.DiscriminatorId == discriminatorId) .Select(mapper.DeserializeTimeStampedData); @@ -58,19 +60,6 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar return mappedDtos; }); - //var genericMapperType = typeof(TimestampedSetMapper<>).MakeGenericType(type); - - //var ttype = typeof(TimestampedSetMapper); - //object b = 0; - - //var mapper = MapperMethodInfo - // .MakeGenericMethod([type]) - // .Invoke(this, [discriminatorId]); - - //var deserializeMethod = genericMapperType - // .GetMethod(nameof(TimestampedSetMapper.DeserializeTimeStampedData))!; - // ToDo: приводим к Dictionary - return result; } @@ -113,13 +102,5 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar client.Dispose(); } - private TimestampedSetMapper GetMapper(Guid idDiscriminator, Type type) - { - return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type)); - } - - private TimestampedSetMapper GetMapper(Guid idDiscriminator) - { - return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T))); - } + } diff --git a/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs b/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs new file mode 100644 index 0000000..ab0d91c --- /dev/null +++ b/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs @@ -0,0 +1,29 @@ +using DD.Persistence.Client.Clients.Mapping.Abstractions; +using DD.Persistence.Models.Configurations; +using System; +using System.Collections.Concurrent; + +namespace DD.Persistence.Client.Clients.Mapping; +internal class MapperStorage : IMapperStorage +{ + private readonly ConcurrentDictionary mapperCache = new(); + private readonly MappingConfig mappingConfigs; + public MapperStorage(MappingConfig mappingConfigs) + { + this.mappingConfigs = mappingConfigs; + } + + + public TimestampedSetMapper? GetMapper(Guid idDiscriminator) + { + if(mappingConfigs.TryGetValue(idDiscriminator, out var type)) + return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type)); + + return null; + } + + public TimestampedSetMapper GetMapper(Guid idDiscriminator) + { + return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T))); + } +} diff --git a/DD.Persistence.Client/DependencyInjection.cs b/DD.Persistence.Client/DependencyInjection.cs index a772b9b..f759bd8 100644 --- a/DD.Persistence.Client/DependencyInjection.cs +++ b/DD.Persistence.Client/DependencyInjection.cs @@ -1,8 +1,10 @@ using DD.Persistence.Client.Clients; using DD.Persistence.Client.Clients.Interfaces; +using DD.Persistence.Client.Clients.Mapping; using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Client.Clients.Mapping.Clients; using DD.Persistence.Models; +using DD.Persistence.Models.Configurations; using Microsoft.Extensions.DependencyInjection; namespace DD.Persistence.Client; @@ -17,7 +19,7 @@ public static class DependencyInjection /// /// /// - public static IServiceCollection AddPersistenceClients(this IServiceCollection services, Dictionary? setpointTypeConfigs = null) + public static IServiceCollection AddPersistenceClients(this IServiceCollection services) { services.AddTransient(typeof(IRefitClientFactory<>), typeof(RefitClientFactory<>)); services.AddTransient(); @@ -31,18 +33,13 @@ public static class DependencyInjection } - public static IServiceCollection AddPersistenceMapping(this IServiceCollection services, Dictionary? mappingConfigs) + public static IServiceCollection AddPersistenceMapping(this IServiceCollection services, MappingConfig mappingConfigs) { - services.AddTransient(provider => - { - var client = provider.GetRequiredService(); - return new SetpointMappingClient(client, mappingConfigs); - }); - services.AddTransient(provider => - { - var client = provider.GetRequiredService(); - return new TimestampedMappingClient(client, mappingConfigs); - }); + services.AddSingleton(mappingConfigs); + services.AddSingleton(); + + services.AddTransient(); + services.AddTransient(); return services; } } diff --git a/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs index 7315496..a2080b0 100644 --- a/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs @@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Client.Clients.Mapping.Clients; using DD.Persistence.Database.Entity; +using DD.Persistence.Models.Configurations; using Microsoft.Extensions.DependencyInjection; using System.Text.Json; using Xunit; @@ -28,7 +29,7 @@ namespace DD.Persistence.IntegrationTests.Controllers { var id = Guid.Parse("e0fcad22-1761-476e-a729-a3c59d51ba41"); - var config = new Dictionary(); + var config = new MappingConfig(); config[id] = typeof(float); var setpointMapper = new SetpointMappingClient(setpointClient, config); diff --git a/DD.Persistence.Models/Configurations/MappingConfig.cs b/DD.Persistence.Models/Configurations/MappingConfig.cs new file mode 100644 index 0000000..bc9f85e --- /dev/null +++ b/DD.Persistence.Models/Configurations/MappingConfig.cs @@ -0,0 +1,4 @@ +namespace DD.Persistence.Models.Configurations; +public class MappingConfig : Dictionary +{ +} diff --git a/DD.Persistence.Test/MappingClientsTest.cs b/DD.Persistence.Test/MappingClientsTest.cs index fac46e4..78648f9 100644 --- a/DD.Persistence.Test/MappingClientsTest.cs +++ b/DD.Persistence.Test/MappingClientsTest.cs @@ -1,6 +1,8 @@ using DD.Persistence.Client.Clients.Interfaces; +using DD.Persistence.Client.Clients.Mapping; using DD.Persistence.Client.Clients.Mapping.Clients; using DD.Persistence.Models; +using DD.Persistence.Models.Configurations; using NSubstitute; using System.Text.Json; @@ -15,17 +17,19 @@ public class MappingClientsTest private readonly ITimestampedValuesClient timestampedValuesClient = Substitute.For(); private readonly TimestampedMappingClient timestampedMappingClient; - private readonly Dictionary mappingConfigs = new Dictionary() - { - { Guid.NewGuid(), typeof(FirstTestDto) }, - { Guid.NewGuid(), typeof(SecondTestDto) } - }; + private readonly MappingConfig mappingConfigs; + public MappingClientsTest() { - timestampedMappingClient = new TimestampedMappingClient(timestampedValuesClient, mappingConfigs); + mappingConfigs = GetConfig(); + var storage = new MapperStorage(mappingConfigs); + + timestampedMappingClient = new TimestampedMappingClient(timestampedValuesClient, storage); } + + [Fact] public async Task GetMultiMapped() { @@ -82,4 +86,12 @@ public class MappingClientsTest expectedId = getResult[1].Values[nameof(SecondTestDto.Id)].ToString(); Assert.Equal(expectedId, actualId); } + private MappingConfig GetConfig() + { + var config = new MappingConfig(); + config[Guid.NewGuid()] = typeof(FirstTestDto); + config[Guid.NewGuid()] = typeof(SecondTestDto); + + return config; + } } diff --git a/Directory.Build.props b/Directory.Build.props index cffb4fe..74c5ac9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -8,6 +8,9 @@ <_Parameter1>DD.Persistence.IntegrationTests + + <_Parameter1>DD.Persistence.Test + <_Parameter1>DynamicProxyGenAssembly2 From 1e2fa287a01105d1b0627fd658ee660f6dd06b29 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Fri, 28 Feb 2025 13:15:27 +0500 Subject: [PATCH 7/7] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=D0=BC=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Mapping/Clients/SetpointMappingClient.cs | 8 +++--- .../Clients/TimestampedMappingClient.cs | 1 + .../Clients/Mapping/MapperStorage.cs | 12 ++++++--- .../Clients/Mapping/TimestampedSetMapper.cs | 26 +++++++++++++++---- DD.Persistence.Test/MappingClientsTest.cs | 4 ++- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs index a090d4d..1942ad4 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/SetpointMappingClient.cs @@ -13,6 +13,7 @@ public class SetpointMappingClient : ISetpointMappingClient private readonly ISetpointClient setpointClient; private readonly MappingConfig mappingConfigs; + /// public SetpointMappingClient(ISetpointClient setpointClient, MappingConfig mappingConfigs) { this.setpointClient = setpointClient; @@ -62,11 +63,11 @@ public class SetpointMappingClient : ISetpointMappingClient /// public async Task> GetPart(DateTimeOffset dateBegin, int take, CancellationToken token) { - var res = await setpointClient.GetPart(dateBegin, take, token); + var result = await setpointClient.GetPart(dateBegin, take, token); - DeserializeList(res); + DeserializeList(result); - return res; + return result; } /// @@ -81,6 +82,7 @@ public class SetpointMappingClient : ISetpointMappingClient public void Dispose() { setpointClient.Dispose(); + } private object DeserializeValue(Guid key, JsonElement value) diff --git a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs index 0d73376..09aa283 100644 --- a/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs +++ b/DD.Persistence.Client/Clients/Mapping/Clients/TimestampedMappingClient.cs @@ -2,6 +2,7 @@ using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Models; using DD.Persistence.Models.Common; +using Microsoft.Extensions.Logging; namespace DD.Persistence.Client.Clients.Mapping.Clients; diff --git a/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs b/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs index ab0d91c..74d33d7 100644 --- a/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs +++ b/DD.Persistence.Client/Clients/Mapping/MapperStorage.cs @@ -1,5 +1,6 @@ using DD.Persistence.Client.Clients.Mapping.Abstractions; using DD.Persistence.Models.Configurations; +using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; @@ -8,22 +9,25 @@ internal class MapperStorage : IMapperStorage { private readonly ConcurrentDictionary mapperCache = new(); private readonly MappingConfig mappingConfigs; - public MapperStorage(MappingConfig mappingConfigs) + private readonly ILogger logger; + + public MapperStorage(MappingConfig mappingConfigs, ILogger logger) { this.mappingConfigs = mappingConfigs; + this.logger = logger; } public TimestampedSetMapper? GetMapper(Guid idDiscriminator) { - if(mappingConfigs.TryGetValue(idDiscriminator, out var type)) - return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type)); + if (mappingConfigs.TryGetValue(idDiscriminator, out var type)) + return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type, logger)); return null; } public TimestampedSetMapper GetMapper(Guid idDiscriminator) { - return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T))); + return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T), logger)); } } diff --git a/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs b/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs index 1911d09..38c1bea 100644 --- a/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs +++ b/DD.Persistence.Client/Clients/Mapping/TimestampedSetMapper.cs @@ -1,4 +1,5 @@ using DD.Persistence.Models; +using Microsoft.Extensions.Logging; using System.Collections.Concurrent; using System.Reflection; using System.Runtime.CompilerServices; @@ -9,13 +10,16 @@ namespace DD.Persistence.Client.Clients.Mapping; internal class TimestampedSetMapper { private readonly Type entityType; + private readonly ILogger logger; + public Guid IdDiscriminator { get; } private readonly ConcurrentDictionary PropertyCache = new(); - public TimestampedSetMapper(Guid idDiscriminator, Type entityType) + public TimestampedSetMapper(Guid idDiscriminator, Type entityType, ILogger logger) { IdDiscriminator = idDiscriminator; this.entityType = entityType; + this.logger = logger; } public object DeserializeTimeStampedData(TimestampedValuesDto data) @@ -66,7 +70,10 @@ internal class TimestampedSetMapper var value = element.Deserialize(property.PropertyType); property.SetValue(entity, value); } - catch (Exception) { } + catch (Exception ex) + { + logger.LogError(ex.Message); + } } private void SetPropertyValueForStruct(ref object entity, string propertyName, object value) { @@ -79,7 +86,10 @@ internal class TimestampedSetMapper var convertedValue = Convert.ChangeType(value, property.PropertyType); property.SetValue(entity, convertedValue); } - catch (Exception) { } + catch (Exception ex) + { + logger.LogError(ex.Message); + } } @@ -95,7 +105,10 @@ internal class TimestampedSetMapper var value = jsonElement.Deserialize(property.PropertyType); property.SetValue(entity, value); } - catch (Exception) { } + catch (Exception ex) + { + logger.LogError(ex.Message); + } } private void SetPropertyValue(ref object entity, string propertyName, object value) @@ -109,7 +122,10 @@ internal class TimestampedSetMapper var convertedValue = Convert.ChangeType(value, property.PropertyType); property.SetValue(entity, convertedValue); } - catch (Exception) { } + catch (Exception ex) + { + logger.LogError(ex.Message); + } } private PropertyInfo? GetPropertyInfo(string propertyName) diff --git a/DD.Persistence.Test/MappingClientsTest.cs b/DD.Persistence.Test/MappingClientsTest.cs index 78648f9..b5d2e70 100644 --- a/DD.Persistence.Test/MappingClientsTest.cs +++ b/DD.Persistence.Test/MappingClientsTest.cs @@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients.Mapping; using DD.Persistence.Client.Clients.Mapping.Clients; using DD.Persistence.Models; using DD.Persistence.Models.Configurations; +using Microsoft.Extensions.Logging; using NSubstitute; using System.Text.Json; @@ -15,6 +16,7 @@ public record SecondTestDto(Guid DiscriminatorId, DateTimeOffset Timestamp, int public class MappingClientsTest { private readonly ITimestampedValuesClient timestampedValuesClient = Substitute.For(); + private readonly ILogger logger = Substitute.For>(); private readonly TimestampedMappingClient timestampedMappingClient; private readonly MappingConfig mappingConfigs; @@ -23,7 +25,7 @@ public class MappingClientsTest public MappingClientsTest() { mappingConfigs = GetConfig(); - var storage = new MapperStorage(mappingConfigs); + var storage = new MapperStorage(mappingConfigs, logger); timestampedMappingClient = new TimestampedMappingClient(timestampedValuesClient, storage); }