Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 方法的缓存属性?_C#_.net_Asp.net_Caching - Fatal编程技术网

C# 方法的缓存属性?

C# 方法的缓存属性?,c#,.net,asp.net,caching,C#,.net,Asp.net,Caching,也许这是在做梦,但是有没有可能创建一个属性来缓存函数的输出(比如,在HttpRuntime.Cache中)并从缓存返回值,而不是在函数的参数相同时实际执行函数 当我说函数时,我指的是任何函数,无论它是从数据库中获取数据,还是添加两个整数,还是吐出文件的内容。任何功能。您的最佳选择是。我不知道他们是否有你需要的东西,但这确实值得检查。顺便说一下,如果你找到答案,一定要在这里公布 编辑:此外,谷歌搜索“postsharp缓存”会提供一些链接,如以下链接: 更新:我最近偶然发现了这篇文章:。它描述了一

也许这是在做梦,但是有没有可能创建一个属性来缓存函数的输出(比如,在HttpRuntime.Cache中)并从缓存返回值,而不是在函数的参数相同时实际执行函数

当我说函数时,我指的是任何函数,无论它是从数据库中获取数据,还是添加两个整数,还是吐出文件的内容。任何功能。

您的最佳选择是。我不知道他们是否有你需要的东西,但这确实值得检查。顺便说一下,如果你找到答案,一定要在这里公布

编辑:此外,谷歌搜索“postsharp缓存”会提供一些链接,如以下链接:


更新:我最近偶然发现了这篇文章:。它描述了一个基于postsharp的库,如果您仍在寻找解决方案。

您可以使用逗号分隔的字符串将字典添加到类中,该字符串包括函数名作为键,结果作为值。然后,当您的函数可以检查字典中是否存在该值时。将字典保存在缓存中,以便所有用户都可以使用它。

好的,坦白说,没有


但这将是一项在框架内实现的任务,以使其在所有情况下都能为每个人通用-然而,您可以通过简单地(显然,简单性与需求相关)使用抽象来定制一些足以满足需求的东西,继承和现有。

如果您想创建一个
[Cache]
属性(或类似属性),您可以在任何地方使用任何方法,那么PostSharp就是您的一站式解决方案。以前,当我使用PostSharp时,我无法克服它使我的构建速度有多慢(这是在2007年,所以这可能不再相关)

另一种解决方案是将ASP.NET MVC中的
Render.Partial
OutputCaching
结合使用。这是为小部件/页面区域提供html的一个很好的解决方案

MVC的另一个解决方案是将
[Cache]
属性实现为
ActionFilterAttribute
。这将允许您获取控制器方法并将其标记为缓存。它只适用于控制器方法,因为AOP魔术只能在MVC管道中使用
ActionFilterAttributes


通过
ActionFilterAttribute
实现AOP已经成为我的商店的goto解决方案。

我也有同样的问题-我的应用程序中有很多昂贵的方法,我有必要缓存这些结果。不久前,我只是复制粘贴的类似代码,但后来我决定将此逻辑排除在我的域之外。 我以前就是这样做的:

    static List<News> _topNews = null;
    static DateTime _topNewsLastUpdateTime = DateTime.MinValue;
    const int CacheTime = 5;  // In minutes

    public IList<News> GetTopNews()
    {
        if (_topNewsLastUpdateTime.AddMinutes(CacheTime) < DateTime.Now)
        {
            _topNews = GetList(TopNewsCount);
        }

        return _topNews;
    }
静态列表_topNews=null;
静态DateTime\u topNewsLastUpdateTime=DateTime.MinValue;
常量int CacheTime=5;//几分钟后
公共IList GetTopNews()
{
如果(\u topNewsLastUpdateTime.AddMinutes(CacheTime)
这就是我现在可以写的:

    public IList<News> GetTopNews()
    {
        return Cacher.GetFromCache(() => GetList(TopNewsCount));
    }
public IList GetTopNews()
{
返回Cacher.GetFromCache(()=>GetList(TopNewsCount));
}
Cacher-是一个简单的帮助器类,如下所示:

public static class Cacher
{
    const int CacheTime = 5;  // In minutes

    static Dictionary<long, CacheItem> _cachedResults = new Dictionary<long, CacheItem>();

    public static T GetFromCache<T>(Func<T> action)
    {
        long code = action.GetHashCode();

        if (!_cachedResults.ContainsKey(code))
        {
            lock (_cachedResults)
            {
                if (!_cachedResults.ContainsKey(code))
                {
                    _cachedResults.Add(code, new CacheItem { LastUpdateTime = DateTime.MinValue });
                }
            }
        }

        CacheItem item = _cachedResults[code];
        if (item.LastUpdateTime.AddMinutes(CacheTime) >= DateTime.Now)
        {
            return (T)item.Result;
        }

        T result = action();

        _cachedResults[code] = new CacheItem
        {
            LastUpdateTime = DateTime.Now,
            Result = result
        };

        return result;
    }
}


class CacheItem
{
    public DateTime LastUpdateTime { get; set; }
    public object Result { get; set; }
}
公共静态类缓存器
{
const int CacheTime=5;//以分钟为单位
静态字典_cachedResults=新字典();
公共静态T GetFromCache(函数操作)
{
long code=action.GetHashCode();
if(!\u cachedResults.ContainsKey(代码))
{
锁定(缓存结果)
{
if(!\u cachedResults.ContainsKey(代码))
{
_Add(代码,新的CacheItem{LastUpdateTime=DateTime.MinValue});
}
}
}
CacheItem项目=_cachedResults[代码];
if(item.LastUpdateTime.AddMinutes(CacheTime)>=DateTime.Now)
{
返回(T)项结果;
}
T结果=动作();
_cachedResults[代码]=新的CacheItem
{
LastUpdateTime=日期时间。现在,
结果=结果
};
返回结果;
}
}
类缓存项
{
公共日期时间LastUpdateTime{get;set;}
公共对象结果{get;set;}
}

关于Cacher的几句话。您可能会注意到,我在计算结果时不使用Monitor.Enter()(lock(…)。这是因为复制CacheItem指针(return(T)\u cachedResults[code].Result;line)是线程安全的操作-只需一个笔划即可执行。另外,如果多个线程同时更改此指针也可以-它们都将有效。

如果您不需要属性配置,但接受代码配置,那么这可能就是您想要的吗?

可能您正在谈论模拟?我想知道使用
动态
实现这一点有多可行。创建一个包装器,该包装器接受动态调用,调用实际对象并缓存来自它们的结果。@Matt Greer您不需要动态来实现类似的目标,因为您已经接受放弃使用AOP。我创建了一个基类
Cacheable
,您所要做的就是从它继承,定义一个缓存区域,并给它一个lambda语句,说明如何在缓存未命中时加载缓存。@Chris Marisic--您介意共享您的
Cacheable
类吗?我想看看。@PostgresQLNewb:我用今天找到的一个新链接更新了我的旧答案,以防万一你仍然对这个东西感兴趣。无论如何,函数名对于键显然是不够的,我认为它必须依赖于参数。但是我很确定在方法的开头添加普通的缓存/检索代码不是OP想要的,但是当另一个线程插入值时,从字典中读取(
TryGetValue
)是线程安全的吗?在