using Microsoft.Extensions.Caching.Memory; using Mirea.Api.Security.Common.Interfaces; using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace Mirea.Api.Endpoint.Common.Services.Security; public class MemoryCacheService(IMemoryCache cache) : ICacheService { public Task SetAsync(string key, T value, TimeSpan? absoluteExpirationRelativeToNow = null, TimeSpan? slidingExpiration = null, CancellationToken cancellationToken = default) { var options = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow, 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) { 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) { cache.Remove(key); return Task.CompletedTask; } }