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