C# MemoryCache学习笔记

原文网址:https://www.cnblogs.com/atomy/archive/2020/02/27/12372678.html

很多情况下需要用到缓存,合理利用缓存一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力。为了避免每次请求都去访问后台的资源(例如数据库),一般会考虑将一些更新不是很频繁的、可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这些保存起来的数据,这种机制就是所谓的缓存机制。

    .NET 4.0的缓存功能主要由三部分组成:System.Runtime.Caching,System.Web.Caching.Cache和Output Cache。

    MemoryCache:这个是在.NET 4.0中新增的缓存框架,Namespace:System.Runtime.Caching ,Assembly:System.Runtime.Caching.dll。

    System.Web.Caching.Cache:这个是在.NET 2.0开始就一直存在的缓存对象,一般主要用在Web中,当然也可以用于Winform里面,不过要引用System.Web.dll。

    Output Cache:这个是在Asp.NET里面使用的。在ASP.NET 4.0之前,都是直接使用System.Web.Caching.Cache来缓存HTML片段。在ASP.NET 4.0中对它进行了重新设计,提供了一个OutputCacheProvider供开发人员进行扩展,但是它默认情况下,仍然使用System.Web.Caching.Cache来做做缓存。

    下面演示MemoryCache的简单使用:

    1、添加一个类,命名为ConfigHelper,代码如下:

复制代码

/// <summary>
/// 配置帮助类
/// </summary>
class ConfigHelper
{
/// <summary>
/// 获取管理配置文件对象
/// </summary>
/// <param name="configPath">指定要管理的配置文件路径,如果为空或不存在,则为管理程序集默认的配置文件路径。</param>
/// <returns></returns>
private static Configuration GetConfiguration(string configPath = null)
{
if (!string.IsNullOrEmpty(configPath) && File.Exists(configPath))
{
ExeConfigurationFileMap map = new ExeConfigurationFileMap
{
ExeConfigFilename = configPath
};
return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
}
else
{
return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
}
}

/// <summary>
/// 获取指定配置文件+配置名称的配置项的值
/// </summary>
public static string GetAppSettingValue(string key, string defaultValue = null, string configPath = null)
{
var config = GetConfiguration(configPath);
var appSetting = config.AppSettings.Settings[key];
return appSetting.Value;
}

/// <summary>
/// 获取所有配置值
/// </summary>
public static Dictionary<string, string> GetAppSettingValues(string configPath = null)
{
Dictionary<string, string> settingDic = new Dictionary<string, string>();
var config = GetConfiguration(configPath);
var settings = config.AppSettings.Settings;
foreach (string key in settings.AllKeys)
{
settingDic[key] = settings[key].ToString();
}
return settingDic;
}

/// <summary>
/// 设置配置值(存在则更新,不存在则新增。)
/// </summary>
public static void SetAppSettingValue(string key, string value, string configPath = null)
{
var config = GetConfiguration(configPath);
var setting = config.AppSettings.Settings[key];
if (setting == null)
{
config.AppSettings.Settings.Add(key, value);
}
else
{
setting.Value = value;
}

config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}

/// <summary>
/// 设置多个配置值(存在则更新,不存在则新增)
/// </summary>
public static void SetAppSettingValues(IEnumerable<KeyValuePair<string, string>> settingValues, string configPath = null)
{
var config = GetConfiguration(configPath);
foreach (var item in settingValues)
{
var setting = config.AppSettings.Settings[item.Key];
if (setting == null)
{
config.AppSettings.Settings.Add(item.Key, item.Value);
}
else
{
setting.Value = item.Value;
}
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}

/// <summary>
/// 删除配置值
/// </summary>
public static void RemoveAppSetting(string key, string configPath = null)
{
var config = GetConfiguration(configPath);
config.AppSettings.Settings.Remove(key);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}

/// <summary>
/// 删除多个配置值
/// </summary>
public static void RemoveAppSettings(string configPath = null, params string[] keys)
{
var config = GetConfiguration(configPath);
if (keys != null)
{
foreach (string key in keys)
{
config.AppSettings.Settings.Remove(key);
}
}
else
{
config.AppSettings.Settings.Clear();
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
}

/// <summary>
/// 获取连接字符串
/// </summary>
public static string GetConnectionString(string name, string defaultconnString = null, string configPath = null)
{
var config = GetConfiguration(configPath);
var connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
if (connStringSettings == null)
{
return defaultconnString;
}
return connStringSettings.ConnectionString;
}

/// <summary>
/// 获取指定配置文件+连接名称的连接字符串配置项
/// </summary>
public static ConnectionStringSettings GetConnectionStringSetting(string name, string configPath = null)
{
var config = GetConfiguration(configPath);
var connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
return connStringSettings;
}

/// <summary>
/// 获取所有的连接字符串配置项
/// </summary>
public static Dictionary<string, ConnectionStringSettings> GetConnectionStringSettings(string configPath = null)
{
var config = GetConfiguration(configPath);
var connStringSettingDic = new Dictionary<string, ConnectionStringSettings>();
var connStringSettings = ConfigurationManager.ConnectionStrings;
foreach (ConnectionStringSettings item in connStringSettings)
{
connStringSettingDic[item.Name] = item;
}
return connStringSettingDic;
}

/// <summary>
/// 设置连接字符串的值(存在则更新,不存在则新增。)
/// </summary>
public static void SetConnectionString(string name, string connString, string provider, string configPath = null)
{
var config = GetConfiguration(configPath);
ConnectionStringSettings connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
if (connStringSettings != null)
{
connStringSettings.ConnectionString = connString;
connStringSettings.ProviderName = provider;
}
else
{
connStringSettings = new ConnectionStringSettings(name, connString, provider);
config.ConnectionStrings.ConnectionStrings.Add(connStringSettings);
}

config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
}

/// <summary>
/// 设置多个连接字符串的值(存在则更新,不存在则新增。)
/// </summary>
public static void SetConnectionStrings(IEnumerable<ConnectionStringSettings> connStringSettings, string configPath = null)
{
var config = GetConfiguration(configPath);
foreach (var item in connStringSettings)
{
ConnectionStringSettings connStringSetting = config.ConnectionStrings.ConnectionStrings[item.Name];
if (connStringSetting != null)
{
connStringSetting.ConnectionString = item.ConnectionString;
connStringSetting.ProviderName = item.ProviderName;
}
else
{
config.ConnectionStrings.ConnectionStrings.Add(item);
}
}

config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
}

/// <summary>
/// 删除连接字符串配置项
/// </summary>
public static void RemoveConnectionString(string name, string configPath = null)
{
var config = GetConfiguration(configPath);
config.ConnectionStrings.ConnectionStrings.Remove(name);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
}

/// <summary>
/// 删除多个连接字符串配置项
/// </summary>
public static void RemoveConnectionStrings(string configPath = null, params string[] names)
{
var config = GetConfiguration(configPath);
if (names != null)
{
foreach (string name in names)
{
config.ConnectionStrings.ConnectionStrings.Remove(name);
}
}
else
{
config.ConnectionStrings.ConnectionStrings.Clear();
}
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
}
}

复制代码
    /// <summary>
    /// 配置帮助类
    /// </summary>
    class ConfigHelper
    {
        /// <summary>
        /// 获取管理配置文件对象
        /// </summary>
        /// <param name="configPath">指定要管理的配置文件路径,如果为空或不存在,则为管理程序集默认的配置文件路径。</param>
        /// <returns></returns>
        private static Configuration GetConfiguration(string configPath = null)
        {
            if (!string.IsNullOrEmpty(configPath) && File.Exists(configPath))
            {
                ExeConfigurationFileMap map = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = configPath
                };
                return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            }
            else
            {
                return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            }
        }

        /// <summary>
        /// 获取指定配置文件+配置名称的配置项的值
        /// </summary>
        public static string GetAppSettingValue(string key, string defaultValue = null, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            var appSetting = config.AppSettings.Settings[key];
            return appSetting.Value;
        }

        /// <summary>
        /// 获取所有配置值
        /// </summary>
        public static Dictionary<string, string> GetAppSettingValues(string configPath = null)
        {
            Dictionary<string, string> settingDic = new Dictionary<string, string>();
            var config = GetConfiguration(configPath);
            var settings = config.AppSettings.Settings;
            foreach (string key in settings.AllKeys)
            {
                settingDic[key] = settings[key].ToString();
            }
            return settingDic;
        }

        /// <summary>
        /// 设置配置值(存在则更新,不存在则新增。)
        /// </summary>
        public static void SetAppSettingValue(string key, string value, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            var setting = config.AppSettings.Settings[key];
            if (setting == null)
            {
                config.AppSettings.Settings.Add(key, value);
            }
            else
            {
                setting.Value = value;
            }

            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        /// <summary>
        /// 设置多个配置值(存在则更新,不存在则新增)
        /// </summary>
        public static void SetAppSettingValues(IEnumerable<KeyValuePair<string, string>> settingValues, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            foreach (var item in settingValues)
            {
                var setting = config.AppSettings.Settings[item.Key];
                if (setting == null)
                {
                    config.AppSettings.Settings.Add(item.Key, item.Value);
                }
                else
                {
                    setting.Value = item.Value;
                }
            }
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        /// <summary>
        /// 删除配置值
        /// </summary>
        public static void RemoveAppSetting(string key, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            config.AppSettings.Settings.Remove(key);
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        /// <summary>
        /// 删除多个配置值
        /// </summary>
        public static void RemoveAppSettings(string configPath = null, params string[] keys)
        {
            var config = GetConfiguration(configPath);
            if (keys != null)
            {
                foreach (string key in keys)
                {
                    config.AppSettings.Settings.Remove(key);
                }
            }
            else
            {
                config.AppSettings.Settings.Clear();
            }
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }

        /// <summary>
        /// 获取连接字符串
        /// </summary>
        public static string GetConnectionString(string name, string defaultconnString = null, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            var connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
            if (connStringSettings == null)
            {
                return defaultconnString;
            }
            return connStringSettings.ConnectionString;
        }

        /// <summary>
        /// 获取指定配置文件+连接名称的连接字符串配置项
        /// </summary>
        public static ConnectionStringSettings GetConnectionStringSetting(string name, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            var connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
            return connStringSettings;
        }

        /// <summary>
        /// 获取所有的连接字符串配置项
        /// </summary>
        public static Dictionary<string, ConnectionStringSettings> GetConnectionStringSettings(string configPath = null)
        {
            var config = GetConfiguration(configPath);
            var connStringSettingDic = new Dictionary<string, ConnectionStringSettings>();
            var connStringSettings = ConfigurationManager.ConnectionStrings;
            foreach (ConnectionStringSettings item in connStringSettings)
            {
                connStringSettingDic[item.Name] = item;
            }
            return connStringSettingDic;
        }

        /// <summary>
        /// 设置连接字符串的值(存在则更新,不存在则新增。)
        /// </summary>
        public static void SetConnectionString(string name, string connString, string provider, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            ConnectionStringSettings connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
            if (connStringSettings != null)
            {
                connStringSettings.ConnectionString = connString;
                connStringSettings.ProviderName = provider;
            }
            else
            {
                connStringSettings = new ConnectionStringSettings(name, connString, provider);
                config.ConnectionStrings.ConnectionStrings.Add(connStringSettings);
            }

            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("connectionStrings");
        }

        /// <summary>
        /// 设置多个连接字符串的值(存在则更新,不存在则新增。)
        /// </summary>
        public static void SetConnectionStrings(IEnumerable<ConnectionStringSettings> connStringSettings, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            foreach (var item in connStringSettings)
            {
                ConnectionStringSettings connStringSetting = config.ConnectionStrings.ConnectionStrings[item.Name];
                if (connStringSetting != null)
                {
                    connStringSetting.ConnectionString = item.ConnectionString;
                    connStringSetting.ProviderName = item.ProviderName;
                }
                else
                {
                    config.ConnectionStrings.ConnectionStrings.Add(item);
                }
            }

            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("connectionStrings");
        }

        /// <summary>
        /// 删除连接字符串配置项
        /// </summary>
        public static void RemoveConnectionString(string name, string configPath = null)
        {
            var config = GetConfiguration(configPath);
            config.ConnectionStrings.ConnectionStrings.Remove(name);
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("connectionStrings");
        }

        /// <summary>
        /// 删除多个连接字符串配置项
        /// </summary>
        public static void RemoveConnectionStrings(string configPath = null, params string[] names)
        {
            var config = GetConfiguration(configPath);
            if (names != null)
            {
                foreach (string name in names)
                {
                    config.ConnectionStrings.ConnectionStrings.Remove(name);
                }
            }
            else
            {
                config.ConnectionStrings.ConnectionStrings.Clear();
            }
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("connectionStrings");
        }
    }
复制代码
复制代码

    2、添加一个类,命名为MemoryCacheHelper(注意需引用System.Runtime.Caching.dll),代码如下:

复制代码

/// <summary>
/// 内存缓存帮助类,支持绝对过期时间、滑动过期时间、文件依赖三种缓存方式。
/// </summary>
class MemoryCacheHelper
{
private static readonly object _locker1 = new object(), _locker2 = new object();

/// <summary>
/// 取缓存项,如果不存在则返回空。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static T GetCacheItem<T>(string key)
{
try
{
return (T)MemoryCache.Default[key];
}
catch
{
return default(T);
}
}

/// <summary>
/// 是否包含指定键的缓存项
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool Contains(string key)
{
return MemoryCache.Default.Contains(key);
}

/// <summary>
/// 取缓存项,如果不存在则新增缓存项。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="cachePopulate"></param>
/// <param name="slidingExpiration"></param>
/// <param name="absoluteExpiration"></param>
/// <returns></returns>
public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
{
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");
if (slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");

if (MemoryCache.Default[key] == null)
{
lock (_locker1)
{
if (MemoryCache.Default[key] == null)
{
T cacheValue = cachePopulate();
if (!typeof(T).IsValueType && cacheValue == null) //如果是引用类型且为NULL则不存缓存
{
return cacheValue;
}

var item = new CacheItem(key, cacheValue);
var policy = CreatePolicy(slidingExpiration, absoluteExpiration);

MemoryCache.Default.Add(item, policy);
}
}
}

return (T)MemoryCache.Default[key];
}

/// <summary>
/// 取缓存项,如果不存在则新增缓存项。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="cachePopulate"></param>
/// <param name="dependencyFilePath"></param>
/// <returns></returns>
public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, string dependencyFilePath)
{
if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");

if (MemoryCache.Default[key] == null)
{
lock (_locker2)
{
if (MemoryCache.Default[key] == null)
{
T cacheValue = cachePopulate();
if (!typeof(T).IsValueType && cacheValue == null) //如果是引用类型且为NULL则不存缓存
{
return cacheValue;
}

var item = new CacheItem(key, cacheValue);
var policy = CreatePolicy(dependencyFilePath);

MemoryCache.Default.Add(item, policy);
}
}
}

return (T)MemoryCache.Default[key];
}

/// <summary>
/// 指定缓存项的一组逐出和过期详细信息
/// </summary>
/// <param name="slidingExpiration"></param>
/// <param name="absoluteExpiration"></param>
/// <returns></returns>
private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
{
var policy = new CacheItemPolicy();

if (absoluteExpiration.HasValue)
{
policy.AbsoluteExpiration = absoluteExpiration.Value;
}
else if (slidingExpiration.HasValue)
{
policy.SlidingExpiration = slidingExpiration.Value;
}

policy.Priority = CacheItemPriority.Default;

return policy;
}

/// <summary>
/// 指定缓存项的一组逐出和过期详细信息
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private static CacheItemPolicy CreatePolicy(string filePath)
{
CacheItemPolicy policy = new CacheItemPolicy();
policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string>() { filePath }));
policy.Priority = CacheItemPriority.Default;
return policy;
}

/// <summary>
/// 移除指定键的缓存项
/// </summary>
/// <param name="key"></param>
public static void RemoveCacheItem(string key)
{
if (Contains(key))
{
MemoryCache.Default.Remove(key);
}
}
}

复制代码

    3、添加一个WinForm窗体,命名为Main,并添加一个按钮。

    4、配置App.config:

复制代码
复制代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>
  <connectionStrings>
    <add name ="connString" connectionString="server=.;database=db_test;uid=sa;pwd=********;" />
  </connectionStrings>
</configuration>
复制代码
复制代码

    5、Main窗体代码如下:

复制代码
复制代码
        private void button1_Click(object sender, EventArgs e)
        {
            int times1 = 0, times2 = 0;
            for (int i = 0; i < 10; i++)
            {
                if (MemoryCacheHelper.Contains("connString"))
                {
                    times1++;
                }
                else
                {
                    times2++;
                    string connstr = MemoryCacheHelper.GetOrAddCacheItem("connString", () =>
                    {
                        return ConfigHelper.GetConnectionString("connString", null);
                    }, Application.StartupPath + @"\App.config");
                }
            }
            MessageBox.Show($"内存缓存读取次数:{times1},非内存缓存读取次数:{times2}", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
复制代码
复制代码

    6、运行结果如下:

posted @   MaxBruce  阅读(1444)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
历史上的今天:
2021-11-07 net core WebAPI 初探及连接MySQL
2021-11-07 ASP.NET Core使用EF Core操作MySql数据库
2021-11-07 谈谈分布式事务之一:SOA需要怎样的事务控制方式
2021-11-07 ASP.NET Core中的依赖注入(2):依赖注入(DI)
2020-11-07 spring cloud 项目
2020-11-07 spring cloud 知识总结
点击右上角即可分享
微信分享提示