From 5bc729eb666cc99fb771c7ba1f2cbf49b1d02f1d Mon Sep 17 00:00:00 2001 From: Polianin Nikita Date: Thu, 31 Oct 2024 04:05:40 +0300 Subject: [PATCH] fix: add an implementation for saving primitive data --- .../Security/DistributedCacheService.cs | 31 +++++++++++++++++ .../Services/Security/MemoryCacheService.cs | 34 ++++++++++++++++--- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/Endpoint/Common/Services/Security/DistributedCacheService.cs b/Endpoint/Common/Services/Security/DistributedCacheService.cs index 1d4a32b..3630ae0 100644 --- a/Endpoint/Common/Services/Security/DistributedCacheService.cs +++ b/Endpoint/Common/Services/Security/DistributedCacheService.cs @@ -17,12 +17,43 @@ public class DistributedCacheService(IDistributedCache cache) : ICacheService SlidingExpiration = slidingExpiration }; + var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); + if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime)) + { + await cache.SetStringAsync(key, value?.ToString() ?? string.Empty, options, cancellationToken); + return; + } + var serializedValue = value as byte[] ?? JsonSerializer.SerializeToUtf8Bytes(value); await cache.SetAsync(key, serializedValue, options, cancellationToken); } public async Task GetAsync(string key, CancellationToken cancellationToken = default) { + var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); + + if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime)) + { + var primitiveValue = await cache.GetStringAsync(key, cancellationToken); + + if (string.IsNullOrEmpty(primitiveValue)) + return default; + + if (type == typeof(string)) + return (T?)(object?)primitiveValue; + + var tryParseMethod = type.GetMethod("TryParse", [typeof(string), type.MakeByRefType()]) + ?? throw new NotSupportedException($"Type {type.Name} does not support TryParse."); + + var parameters = new[] { primitiveValue, Activator.CreateInstance(type) }; + var success = (bool)tryParseMethod.Invoke(null, parameters)!; + + if (success) + return (T)parameters[1]!; + + return default; + } + var cachedValue = await cache.GetAsync(key, cancellationToken); return cachedValue == null ? default : JsonSerializer.Deserialize(cachedValue); } diff --git a/Endpoint/Common/Services/Security/MemoryCacheService.cs b/Endpoint/Common/Services/Security/MemoryCacheService.cs index 6c5b8f6..4c7f7fd 100644 --- a/Endpoint/Common/Services/Security/MemoryCacheService.cs +++ b/Endpoint/Common/Services/Security/MemoryCacheService.cs @@ -17,17 +17,41 @@ public class MemoryCacheService(IMemoryCache cache) : ICacheService SlidingExpiration = slidingExpiration }; + var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); + if (type.IsPrimitive || type == typeof(string) || type == typeof(DateTime)) + { + cache.Set(key, value?.ToString() ?? string.Empty, options); + return Task.CompletedTask; + } + cache.Set(key, value as byte[] ?? JsonSerializer.SerializeToUtf8Bytes(value), options); return Task.CompletedTask; } public Task GetAsync(string key, CancellationToken cancellationToken = default) { - return Task.FromResult( - cache.TryGetValue(key, out byte[]? value) ? - JsonSerializer.Deserialize(value) : - default - ); + var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); + + if (!type.IsPrimitive && type != typeof(string) && type != typeof(DateTime)) + return Task.FromResult( + cache.TryGetValue(key, out byte[]? value) ? JsonSerializer.Deserialize(value) : default + ); + + var primitiveValue = cache.Get(key); + + if (string.IsNullOrEmpty(primitiveValue?.ToString())) + return Task.FromResult(default); + + if (type == typeof(string)) + return Task.FromResult((T?)primitiveValue); + + var tryParseMethod = type.GetMethod("TryParse", [typeof(string), type.MakeByRefType()]) + ?? throw new NotSupportedException($"Type {type.Name} does not support TryParse."); + + var parameters = new[] { primitiveValue, Activator.CreateInstance(type) }; + var success = (bool)tryParseMethod.Invoke(null, parameters)!; + + return success ? Task.FromResult((T?)parameters[1]) : Task.FromResult(default); } public Task RemoveAsync(string key, CancellationToken cancellationToken = default)