c# - 如何在 C# UWP 应用程序中实现自定义缓存
问题描述
我有一个 Web 服务 ( ItemWebService ),它调用 API 并获取项目列表 ( productList )。该服务是从UWP 应用程序调用的。
要求是:
- 将产品列表缓存一段时间(例如:1 小时),如果可用且调用时未超时,则返回缓存列表
GetProductListAsync()
则返回缓存列表。 - 无需每小时缓存一次,因为此过程将是一个非常罕见的过程,并且 UWP 应用程序在组织中的多个设备上运行。因此,如果设置一个间隔,API 每小时会同时收到数百个请求。
- 每当从 method 将新项目添加到产品列表时
AddProductAsync(AddProductRequest addProductRequest )
,都应刷新缓存。
解决方案
为满足上述需求,在ItemWebService中实现了自定义缓存。
using NodaTime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Threading.Tasks;
namespace MyNamespace.Products
{
public class ItemWebService : IItemService
{
private readonly IApiRestClient _restClient;
private readonly string _serviceUrl = "api/products";
private static IEnumerable<ProductListItem> _cachedProductist = null;
private readonly IClock _clock;
private readonly Duration _productlistValidFor = Duration.FromHours(1); // Set the timeout
private static Instant _lastUpdate = Instant.MinValue;
public ItemWebService (IApiRestClient restClient)
{
_restClient = restClient;
_clock = SystemClock.Instance; // using NodaTime
}
public async Task AddProductAsync(AddProductRequest addProductRequest)
{
await _restClient.Put($"{_serviceUrl}/add", addProductRequest);
// Expire cache manually to update product list on next call
_lastUpdate = _clock.GetCurrentInstant() - _productlistValidFor ;
}
public async Task<IObservable<ProductListItem>> GetProductListAsync()
{
if (_cachedProductist == null || (_lastUpdate + _productlistValidFor) < _clock.GetCurrentInstant())
{
_cachedProductist = await _restClient.Get<IEnumerable<ProductListItem>>($"{_serviceUrl}/productList");
// Update the last updated time
_lastUpdate = _clock.GetCurrentInstant();
}
return _cachedProductist.ToObservable();
}
}
}
通过这个实现,我能够避免设置一个间隔,该间隔会导致数百个 API 调用(因为有数百个设备运行同一个应用程序)每小时刷新缓存。
现在,每当运行 UWP 应用程序的设备请求产品列表时,该服务将检查该设备上的缓存是否存在且未过期,并在必要时调用服务器刷新缓存。
推荐阅读
- scala - 删除后 Akka 集群节点重新加入
- php - 尝试从 json 获取值时出错
- python - 从 `torch` 或 `numpy` 向量创建 pytorch 张量
- gcc - 当线程清理程序报告数据竞争时如何添加断点?
- ios - Xcode 11 Simulator - 如何自定义模拟设备分辨率
- ios - 尝试在 UIImagePickerController didFinishPickingMediaWithInfo 回调中移动文件失败并出现“您没有权限”错误
- python - 使用 os.system 或 subprocess.Popopen 启动的软件在 python 关闭时关闭
- server - Netty 中的 ReplayingDecoder 在每次迭代中读取 10240 字节
- python - 如何适合第一个标签matplolib python的第二个标签底部
- cmd - 无法从 cmd 在 Documents 中找到文件