配置与扩展


1、配置文件

  通过配置文件可以配置多个缓存管理器,通过更换 default 的值即可实现无缝切换。配置文件如下:

  • .Net Framework 下的 app.config 或 web.config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="fireasy">
      <section name="cachings" type="Fireasy.Common.Caching.Configuration.CachingConfigurationSectionHandler, Fireasy.Common" />
    </sectionGroup>
  </configSections>
  <fireasy>
    <cachings default="redis">
      <caching name="redis" type="Fireasy.Redis.CacheManager, Fireasy.Redis">
        <config defaultDb="2">
          <host server="192.168.1.1" port="6379"></host>
          <host server="192.168.1.2" port="6379"></host>
        </config>
      </caching>
      <caching name="demo" type="demo.CacheManager, demo" />
    </cachings>
  </fireasy>
</configuration>
  • .Net Core 下的 appsettings.json 文件
{
  "fireasy": {
    "cachings": {
      "default": "redis",
      "settings": {
        "redis": {
          "type": "Fireasy.Redis.CacheManager, Fireasy.Redis",
          "config": {
            "defaultDb": 2,
            "hosts": [
              {
                "server": "192.168.1.1",
                "port": 6379
              },
              {
                "server": "192.168.1.2",
                "port": 6379
              }
            ]
          }
        },
        "demo": {
          "type": "demo.CacheManager, demo"
        }
      }
    }
  }
}

  CacheManagerFactory 工厂类可以根据配置创建一个 ICacheManager 实例。如下所示:

[TestMethod]
public void TestCreateManager()
{
    var manager1 = CacheManagerFactory.CreateManager();
    Assert.IsNotNull(manager1); //RedisCacheManager

    var manager2 = CacheManagerFactory.CreateManager("demo");
    Assert.IsNotNull(manager2); //demo
}

  在使用 IOC 的环境中,通过构造注入或属性注入得到的 ICacheManager 的实例对应的是指向 default 的配置项。


2、缓存键标准化

  Fireasy 提供了 ICacheKeyNormalizer 接口,通过外部去构造特殊的缓存键,缓存需要按企业、机构或群组等进行存储时,可以通过这个接口的实现去格式化缓存键,而不是在使用 ICacheManager 接口的方法时去处理缓存键。如下所示:

public class CacheKeyNormalizer : ICacheKeyNormalizer
{
    public string NormalizeKey(string cacheKey, object specialKey = null)
    {
        if (cacheKey.StartsWith("demo_"))
        {
            return cacheKey;
        }

        return string.Concat("demo_", specialKey ?? GetCompanyCode(), ":", cacheKey);
    }
        
    private string GetCompanyCode()
    {
        if (HttpContext.Current.Request.Cookies.TryGetValue(KEY, out string value) &&
          !string.IsNullOrEmpty(value))
        {
            return value;
        }

        return null;
    }
}

  以上代码演示了如果从 cookies 里读取企业编码作为缓存键的前缀,以实现缓存的隔离。下面是 .Net Core 版本的代码:

public class CacheKeyNormalizer : ICacheKeyNormalizer
{
    private readonly IHttpContext _httpContext;
        
    public CacheKeyNormalizer(IHttpContextAccessor accessor)
    {
        _httpContext = accessor.HttpContext;
    }
        
    public string NormalizeKey(string cacheKey, object specialKey = null)
    {
        if (cacheKey.StartsWith("demo_"))
        {
            return cacheKey;
        }

        return string.Concat("demo_", specialKey ?? GetCompanyCode(), ":", cacheKey);
    }
        
    private string GetCompanyCode()
    {
        if (_httpContext.Request.Cookies.TryGetValue(KEY, out string value) &&
          !string.IsNullOrEmpty(value))
        {
            return value;
        }

        return null;
    }
}

  将 CacheKeyNormalizer 类配置到 IOC 中,即可实现缓存键的标准化。


3、独立内存存储

  默认情况下,不管你是否使用 MemoryCacheManager 的默认实例,还是创建不同的实例,都会使用相同的内存空间存储缓存项。如果想为不同的实例使用不同的存储空间,则可以实现 IMemoryCacheStrategy 接口,将 UseStandaloneStorage 属性返回为 true 即可。如下所示:

public class MemoryCacheStrategy : IMemoryCacheStrategy
{
    public bool UseStandaloneStorage => true;
}

  将 MemoryCacheStrategy 类配置到 IOC 中,即可实现内存的独立存储。


4、第三方适配