C# 通用 Cache 类开发指南

C# 通用 Cache 类开发指南

解决方案goocz2025-06-15 17:22:562A+A-

在现代应用程序中,缓存是一种有效的优化手段,能够显著提高系统的性能,减少延迟。缓存可以用于数据库查询结果的存储、API 响应的缓存、复杂计算结果的保存等多个场景。本文将介绍如何开发一个通用的 CacheService 类,并展示其在不同场景中的应用。

引言

缓存是一种存储机制,用于临时性地保存数据,以减少数据获取的时间和频次。在高性能应用程序中,合理使用缓存,可以显著提高系统的响应速度,减轻后台服务的负担。接下来我们讲解如何开发一个通用的 CacheService 并展示其在具体场景中的应用。

开发通用的 CacheService

ICacheService 接口

首先,定义一个 ICacheService 接口,定义基本的缓存操作:

using System;
using System.Threading.Tasks;

public interface ICacheService
{
    void Set<T>(string key, T value, TimeSpan expiration);
    T Get<T>(string key);
    Task SetAsync<T>(string key, T value, TimeSpan expiration);
    Task<T> GetAsync<T>(string key);
    void Remove(string key);
    Task RemoveAsync(string key);
}

CacheService 实现

接下来,开发 CacheService 类,它实现了 ICacheService 接口。该类同时支持内存缓存和分布式缓存(例如 Redis),基于启动时的配置选择缓存方式:

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;

public class CacheService : ICacheService
{
    private readonly IMemoryCache _memoryCache;
    private readonly IDistributedCache _distributedCache;
    private readonly ILogger<CacheService> _logger;
    private readonly bool _useDistributedCache;

    public CacheService(IMemoryCache memoryCache, IDistributedCache distributedCache, ILogger<CacheService> logger, bool useDistributedCache = false)
    {
        _memoryCache = memoryCache;
        _distributedCache = distributedCache;
        _logger = logger;
        _useDistributedCache = useDistributedCache;
    }

    public void Set<T>(string key, T value, TimeSpan expiration)
    {
        if (_useDistributedCache)
        {
            var options = new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = expiration
            };
            var serializedValue = System.Text.Json.JsonSerializer.Serialize(value);
            _distributedCache.SetString(key, serializedValue, options);
        }
        else
        {
            var cacheEntryOptions = new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = expiration
            };
            _memoryCache.Set(key, value, cacheEntryOptions);
        }
    }

    public T Get<T>(string key)
    {
        if (_useDistributedCache)
        {
            var serializedValue = _distributedCache.GetString(key);
            if (serializedValue != null)
            {
                return System.Text.Json.JsonSerializer.Deserialize<T>(serializedValue);
            }
            return default;
        }
        _memoryCache.TryGetValue(key, out T value);
        return value;
    }

    public async Task SetAsync<T>(string key, T value, TimeSpan expiration)
    {
        if (_useDistributedCache)
        {
            var options = new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = expiration
            };
            var serializedValue = System.Text.Json.JsonSerializer.Serialize(value);
            await _distributedCache.SetStringAsync(key, serializedValue, options);
        }
        else
        {
            var cacheEntryOptions = new MemoryCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = expiration
            };
            _memoryCache.Set(key, value, cacheEntryOptions);
        }
    }

    public async Task<T> GetAsync<T>(string key)
    {
        if (_useDistributedCache)
        {
            var serializedValue = await _distributedCache.GetStringAsync(key);
            if (serializedValue != null)
            {
                return System.Text.Json.JsonSerializer.Deserialize<T>(serializedValue);
            }
            return default;
        }
        _memoryCache.TryGetValue(key, out T value);
        return await Task.FromResult(value);
    }

    public void Remove(string key)
    {
        if (_useDistributedCache)
        {
            _distributedCache.Remove(key);
        }
        else
        {
            _memoryCache.Remove(key);
        }
    }

    public async Task RemoveAsync(string key)
    {
        if (_useDistributedCache)
        {
            await _distributedCache.RemoveAsync(key);
        }
        else
        {
            _memoryCache.Remove(key);
        }
    }
}

配置依赖注入

在项目的 Program.cs 中配置依赖注入:

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;

public class Program
{
    static void Main(string[] args)
    {
      var serviceProvider = new ServiceCollection()
     .AddMemoryCache()
     .AddStackExchangeRedisCache(options =>
     {
         options.Configuration = "localhost:6379";
     })
     .AddLogging()
     .AddSingleton<CacheService>()
     .BuildServiceProvider();
  
      // 使用缓存服务的示例
      var cacheService = serviceProvider.GetService<CacheService>();
  
      cacheService.Set("key1", "value1",new TimeSpan(0, 10, 0));
      var value = cacheService.Get<string>("key1");
  }

}

我们还可以启用分布试的缓冲(Redis)

static void Main(string[] args)
{
    var serviceProvider = new ServiceCollection()
   .AddMemoryCache()
   .AddStackExchangeRedisCache(options =>
   {
       options.Configuration = "localhost:6379";
   })
   .AddLogging()
    .AddSingleton<CacheService>(sp =>
    {
        var memoryCache = sp.GetRequiredService<IMemoryCache>();
        var distributedCache = sp.GetRequiredService<IDistributedCache>();
        var logger = sp.GetRequiredService<ILogger<CacheService>>();
        return new CacheService(memoryCache, distributedCache, logger, useDistributedCache: true);
    })
   .BuildServiceProvider();

    // 使用缓存服务的示例
    var cacheService = serviceProvider.GetService<CacheService>();

    cacheService.Set("key1", "value1",new TimeSpan(0, 10, 0));
    var value = cacheService.Get<string>("key1");
}

缓存应用场景示例

数据库查询结果缓存

DatabaseService.cs

using System;

public class DatabaseService
{
    private readonly ICacheService _cacheService;

    public DatabaseService(ICacheService cacheService)
    {
        _cacheService = cacheService;
    }

    public string GetDataFromDatabase(string query)
    {
        string cacheKey = #34;DatabaseQuery-{query}";
        var cacheData = _cacheService.Get<string>(cacheKey);

        if (cacheData != null)
        {
            return cacheData;
        }

        // 模拟数据库查询操作
        string data = "返回数据";
        _cacheService.Set(cacheKey, data, TimeSpan.FromMinutes(5));
        return data;
    }
}

程序入口

internal class Program
{
    static void Main(string[] args)
    {
        var serviceProvider = new ServiceCollection()
        .AddMemoryCache()
        .AddStackExchangeRedisCache(options =>
        {
            options.Configuration = "localhost:6379";
        })
        .AddLogging()
        .AddSingleton<CacheService>()
        .AddSingleton<ICacheService, CacheService>()
        .AddSingleton<DatabaseService>()
        .BuildServiceProvider();

        var databaseService = serviceProvider.GetService<DatabaseService>();
        string query = "SELECT * FROM Users";
        Console.WriteLine("Query Result: " + databaseService.GetDataFromDatabase(query));

        // 再次调用以展示缓存效果
        Console.WriteLine("Query Result from Cache: " + databaseService.GetDataFromDatabase(query));
    }
}

API 响应缓存

ApiService.cs

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class ApiService
{
    private readonly ICacheService _cacheService;
    private readonly HttpClient _httpClient;

    public ApiService(ICacheService cacheService, HttpClient httpClient)
    {
        _cacheService = cacheService;
        _httpClient = httpClient;
    }

    public async Task<string> GetApiResponseAsync(string url)
    {
        string cacheKey = #34;ApiUrl-{url}";
        var cacheData = await _cacheService.GetAsync<string>(cacheKey);

        if (cacheData != null)
        {
            return cacheData;
        }

        var response = await _httpClient.GetStringAsync(url);
        await _cacheService.SetAsync(cacheKey, response, TimeSpan.FromMinutes(10));
        return response;
    }
}

程序入口

using System.Net.Http;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        var serviceProvider = new ServiceCollection()
            .AddMemoryCache()
            .AddStackExchangeRedisCache(options =>
            {
                options.Configuration = "localhost:6379";
            })
            .AddLogging()
            .AddSingleton<HttpClient>()
            .AddSingleton<CacheService>()
            .AddSingleton<ICacheService, CacheService>()
            .AddSingleton<ApiService>()
            .BuildServiceProvider();

        var apiService = serviceProvider.GetService<ApiService>();
        string apiUrl = "https://jsonplaceholder.typicode.com/posts";
        
        var result = await apiService.GetApiResponseAsync(apiUrl);
        Console.WriteLine("API Response: " + result);

        // 再次调用以展示缓存效果
        var cachedResult = await apiService.GetApiResponseAsync(apiUrl);
        Console.WriteLine("Cached API Response: " + cachedResult);
    }
}

复杂计算结果缓存

CalculationService.cs

using System;

public class CalculationService
{
    private readonly ICacheService _cacheService;

    public CalculationService(ICacheService cacheService)
    {
        _cacheService = cacheService;
    }

    public int HeavyComputation(int input)
    {
        string cacheKey = #34;HeavyComputation-{input}";
        var cacheData = _cacheService.Get<int>(cacheKey);

        if (cacheData != 0)
        {
            return cacheData;
        }

        // 模拟复杂计算
        int result = input * input;
        _cacheService.Set(cacheKey, result, TimeSpan.FromMinutes(10));
        return result;
    }
}

程序入口

public class Program
{
    public static void Main(string[] args)
    {
        var serviceProvider = new ServiceCollection()
            .AddMemoryCache()
            .AddStackExchangeRedisCache(options =>
            {
                options.Configuration = "localhost:6379";
            })
            .AddLogging()
            .AddSingleton<CacheService>()
            .AddSingleton<ICacheService, CacheService>()
            .AddSingleton<CalculationService>()
            .BuildServiceProvider();

        var calculationService = serviceProvider.GetService<CalculationService>();
        int input = 42;
        Console.WriteLine("Computation Result: " + calculationService.HeavyComputation(input));

        // 再次调用以展示缓存效果
        Console.WriteLine("Cached Computation Result: " + calculationService.HeavyComputation(input));
    }
}

总结

本文介绍了如何开发一个通用的 CacheService,并展示了其在不同场景中的应用:数据库查询结果缓存、API 响应缓存、复杂计算结果缓存。这种通用的缓存服务设计,可以显著提高应用的性能和响应速度,减少对外部资源(如数据库、外部 API)的频繁访问,从而优化用户体验。

通过上述示例,开发者可以更轻松地在项目中集成和管理缓存,提高应用的整体性能和可靠性。希望本文对你有所帮助,能够在实际项目中充分利用缓存技术。

点击这里复制本文地址 以上内容由goocz整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

果子教程网 © All Rights Reserved.  蜀ICP备2024111239号-5