From 75f6b5b1c3a6c6f0393a7e6fad016d027a9b0cd7 Mon Sep 17 00:00:00 2001 From: Alex Shibalkin Date: Mon, 20 Jan 2025 15:12:40 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=BC=D0=B0=D0=BF=D0=BF=D0=B8=D0=BD=D0=B3=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20TimeStampedData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interfaces/ITimestampedSetClient.cs | 29 +++- .../Clients/TimestampedSetClient.cs | 35 ++++- .../DD.Persistence.Client.csproj | 8 +- DD.Persistence.Client/TimestampedSetMapper.cs | 135 ++++++++++++++++++ .../DD.Persistence.Models.csproj | 4 +- 5 files changed, 199 insertions(+), 12 deletions(-) create mode 100644 DD.Persistence.Client/TimestampedSetMapper.cs diff --git a/DD.Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs b/DD.Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs index be98a77..432cccb 100644 --- a/DD.Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs +++ b/DD.Persistence.Client/Clients/Interfaces/ITimestampedSetClient.cs @@ -39,13 +39,26 @@ public interface ITimestampedSetClient : IDisposable /// Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); - /// - /// Диапазон дат за которые есть данные + /// + /// Получение данных с фильтрацией. Значение фильтра null - отключен /// /// + /// + /// + /// + /// /// /// - Task GetDatesRange(Guid idDiscriminator, CancellationToken token); + Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token); + + + /// + /// Диапазон дат за которые есть данные + /// + /// + /// + /// + Task GetDatesRange(Guid idDiscriminator, CancellationToken token); /// /// @@ -56,4 +69,14 @@ public interface ITimestampedSetClient : IDisposable /// /// Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token); + + /// + /// + /// + /// + /// + /// + /// + /// + Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token); } \ No newline at end of file diff --git a/DD.Persistence.Client/Clients/TimestampedSetClient.cs b/DD.Persistence.Client/Clients/TimestampedSetClient.cs index 7d1ba56..6295d02 100644 --- a/DD.Persistence.Client/Clients/TimestampedSetClient.cs +++ b/DD.Persistence.Client/Clients/TimestampedSetClient.cs @@ -3,13 +3,18 @@ using DD.Persistence.Client.Clients.Base; using DD.Persistence.Client.Clients.Interfaces; using DD.Persistence.Client.Clients.Interfaces.Refit; using DD.Persistence.Models; +using static System.Runtime.InteropServices.JavaScript.JSType; +using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Reflection; +using System.Collections.Concurrent; namespace DD.Persistence.Client.Clients; public class TimestampedSetClient : BaseClient, ITimestampedSetClient { private readonly IRefitTimestampedSetClient refitTimestampedSetClient; - - public TimestampedSetClient(IRefitClientFactory refitTimestampedSetClientFactory, ILogger logger) : base(logger) + private readonly ConcurrentDictionary mapperCache = new(); + public TimestampedSetClient(IRefitClientFactory refitTimestampedSetClientFactory, ILogger logger) : base(logger) { this.refitTimestampedSetClient = refitTimestampedSetClientFactory.Create(); } @@ -54,10 +59,34 @@ public class TimestampedSetClient : BaseClient, ITimestampedSetClient return result; } - public void Dispose() + public async Task> Get(Guid idDiscriminator, DateTimeOffset? geTimestamp, IEnumerable? columnNames, int skip, int take, CancellationToken token) + { + var data = await Get(idDiscriminator, geTimestamp, columnNames, skip, take, token); + var mapper = GetMapper(idDiscriminator); + + return data.Select(mapper.DeserializeTimeStampedData); + } + + + + public async Task> GetLast(Guid idDiscriminator, IEnumerable? columnNames, int take, CancellationToken token) + { + var data = await GetLast(idDiscriminator, columnNames, 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() { refitTimestampedSetClient.Dispose(); GC.SuppressFinalize(this); } + + } diff --git a/DD.Persistence.Client/DD.Persistence.Client.csproj b/DD.Persistence.Client/DD.Persistence.Client.csproj index 3491596..1e0bc4a 100644 --- a/DD.Persistence.Client/DD.Persistence.Client.csproj +++ b/DD.Persistence.Client/DD.Persistence.Client.csproj @@ -11,9 +11,9 @@ DD.Persistence.Client - 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1 + 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1 - 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1 + 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)).1 DD.Persistence.Client @@ -40,8 +40,8 @@ - 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) - 1.4.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) + 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) + 1.5.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) diff --git a/DD.Persistence.Client/TimestampedSetMapper.cs b/DD.Persistence.Client/TimestampedSetMapper.cs new file mode 100644 index 0000000..521fc18 --- /dev/null +++ b/DD.Persistence.Client/TimestampedSetMapper.cs @@ -0,0 +1,135 @@ +using DD.Persistence.Models; +using System.Collections.Concurrent; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text.Json; + +namespace DD.Persistence.Client; + +internal abstract class TimestampedSetMapperBase +{ + public abstract object Map(TimestampedSetDto data); + +} +internal class TimestampedSetMapper : TimestampedSetMapperBase +{ + private readonly Type entityType = typeof(T); + public Guid IdDiscriminator { get; } + private readonly ConcurrentDictionary PropertyCache = new(); + + public TimestampedSetMapper(Guid idDiscriminator) + { + IdDiscriminator = idDiscriminator; + } + + public override object Map(TimestampedSetDto data) + { + return DeserializeTimeStampedData(data)!; + } + + public T DeserializeTimeStampedData(TimestampedSetDto data) + { + + if (entityType.IsValueType) + return MapStruct(data); + else + return MapClass(data); + } + + private T MapClass(TimestampedSetDto data) + { + var entity = (T)RuntimeHelpers.GetUninitializedObject(typeof(T)); + foreach (var (propertyName, value) in data.Set) + { + if (value is JsonElement jsonElement) + SetPropertyValueFromJson(ref entity, propertyName, jsonElement); + } + SetPropertyValue(ref entity, "Timestamp", data.Timestamp); + return entity; + } + + private T MapStruct(TimestampedSetDto data) + { + var entity = Activator.CreateInstance(); + object boxedEntity = entity!; + foreach (var (propertyName, value) in data.Set) + { + if (value is JsonElement jsonElement) + SetPropertyValueForStructFromJson(ref boxedEntity, propertyName, jsonElement); + } + SetPropertyValueForStruct(ref boxedEntity, "Timestamp", data.Timestamp); + + return (T)boxedEntity; + } + + private void SetPropertyValueForStructFromJson(ref object entity, string propertyName, JsonElement element) + { + var property = GetPropertyInfo(propertyName); + if (property is null) + return; + + try + { + var value = element.Deserialize(property.PropertyType); + property.SetValue(entity, value); + } + catch (Exception ex) + { + } + } + private void SetPropertyValueForStruct(ref object entity, string propertyName, object value) + { + var property = GetPropertyInfo(propertyName); + if (property is null) + return; + + try + { + var convertedValue = Convert.ChangeType(value, property.PropertyType); + property.SetValue(entity, convertedValue); + } + catch (Exception ex) + { + } + } + + + private void SetPropertyValueFromJson(ref T entity, string propertyName, JsonElement jsonElement) + { + var property = GetPropertyInfo(propertyName); + + if (property is null) + return; + + try + { + var value = jsonElement.Deserialize(property.PropertyType); + property.SetValue(entity, value); + } + catch (Exception ex) + { + + } + } + + private void SetPropertyValue(ref T entity, string propertyName, object value) + { + var property = GetPropertyInfo(propertyName); + if (property is null) + return; + + try + { + var convertedValue = Convert.ChangeType(value, property.PropertyType); + property.SetValue(entity, convertedValue); + } + catch (Exception ex) + { + } + } + + private PropertyInfo? GetPropertyInfo(string propertyName) + { + return PropertyCache.GetOrAdd(propertyName, name => entityType.GetProperty(name)); + } +} diff --git a/DD.Persistence.Models/DD.Persistence.Models.csproj b/DD.Persistence.Models/DD.Persistence.Models.csproj index 6bcae66..6facfdc 100644 --- a/DD.Persistence.Models/DD.Persistence.Models.csproj +++ b/DD.Persistence.Models/DD.Persistence.Models.csproj @@ -11,9 +11,9 @@ DD.Persistence.Models - 1.2.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) + 1.3.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) - 1.2.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) + 1.3.$([System.DateTime]::UtcNow.ToString(yyMM.ddHH)) DD.Persistence.Models