C# 需要帮助分析.NET缓存扩展方法吗

C# 需要帮助分析.NET缓存扩展方法吗,c#,.net,caching,C#,.net,Caching,我有以下分机 Public Module CacheExtensions Sub New() End Sub Private sync As New Object() Public Const DefaultCacheExpiration As Integer = 1200 ''# 20 minutes <Extension()> Public Function GetOrStore(Of T)(ByVal cache As Ca

我有以下分机

Public Module CacheExtensions
    Sub New()
    End Sub

    Private sync As New Object()
    Public Const DefaultCacheExpiration As Integer = 1200 ''# 20 minutes

    <Extension()> 
    Public Function GetOrStore(Of T)(ByVal cache As Cache, ByVal key As String, ByVal generator As Func(Of T)) As T
        Return cache.GetOrStore(key, If(generator IsNot Nothing, generator(), Nothing), DefaultCacheExpiration)
    End Function

    <Extension()> 
    Public Function GetOrStore(Of T)(ByVal cache As Cache, ByVal key As String, ByVal generator As Func(Of T), ByVal expireInSeconds As Double) As T
        Return cache.GetOrStore(key, If(generator IsNot Nothing, generator(), Nothing), expireInSeconds)
    End Function

    <Extension()> 
    Public Function GetOrStore(Of T)(ByVal cache As Cache, ByVal key As String, ByVal obj As T) As T
        Return cache.GetOrStore(key, obj, DefaultCacheExpiration)
    End Function

    <Extension()> 
    Public Function GetOrStore(Of T)(ByVal cache As Cache, ByVal key As String, ByVal obj As T, ByVal expireInSeconds As Double) As T
        Dim result = cache(key)

        If result Is Nothing Then

            SyncLock sync
                If result Is Nothing Then
                    result = If(obj IsNot Nothing, obj, Nothing)
                    cache.Insert(key, result, Nothing, DateTime.Now.AddSeconds(expireInSeconds), cache.NoSlidingExpiration)
                End If
            End SyncLock
        End If

        Return DirectCast(result, T)

    End Function

End Module
除了在
\u TagRepository.Read()
上设置断点外,所有这些都非常简单。问题是每次请求都会调用它,而我认为只有当
结果为空时才会调用它

我是不是遗漏了什么

编辑:对你们来说,这是C#等价物

public static class CacheExtensions
{

    private static object sync = new object();
    public const int DefaultCacheExpiration = 20;

    public static T GetOrStore<T>( this Cache cache, string key, Func<T> generator ) {
        return cache.GetOrStore( key, generator != null ? generator() : default( T ), DefaultCacheExpiration );
    }

    public static T GetOrStore<T>( this Cache cache, string key, Func<T> generator, double expireInMinutes ) {
        return cache.GetOrStore( key, generator != null ? generator() : default( T ), expireInMinutes );
    }

    public static T GetOrStore<T>( this Cache cache, string key, T obj ) {
        return cache.GetOrStore( key, obj, DefaultCacheExpiration );
    }

    public static T GetOrStore<T>( this Cache cache, string key, T obj, double expireInMinutes ) {
        var result = cache[key];

        if ( result == null ) {

            lock ( sync ) {
                if ( result == null ) {
                    result = obj != null ? obj : default( T );
                    cache.Insert( key, result, null, DateTime.Now.AddMinutes( expireInMinutes ), Cache.NoSlidingExpiration );
                }
            }
        }

        return (T)result;

    }

}
公共静态类缓存扩展
{
私有静态对象同步=新对象();
public const int DefaultCacheExpiration=20;
公共静态T GetOrStore(此缓存、字符串键、Func生成器){
return cache.GetOrStore(key,generator!=null?generator():default(T),DefaultCacheExpiration);
    }
公共静态T GetOrStore(此缓存、字符串键、Func生成器、双过期分钟){
return cache.GetOrStore(key,generator!=null?generator():默认值(T),expireInMinutes);
    }
公共静态T GetOrStore(此缓存、字符串键、T obj){
返回cache.GetOrStore(key,obj,DefaultCacheExpiration);
    }
公共静态T GetOrStore(此缓存、字符串键、T obj、双过期分钟){
var result=cache[key];
如果(结果==null){
锁定(同步){
如果(结果==null){
结果=obj!=null?obj:默认值(T);
Insert(key,result,null,DateTime.Now.AddMinutes(expireInMinutes),cache.noslidingexpirement);
                }
            }
        }
返回(T)结果;
    }
}
电话呢

    return HttpRuntime.Cache.GetOrStore<List<string>>("TagNamesOnly", () => _TagRepository.Read().Select(t => t.Name).OrderBy(t => t).ToList());
返回HttpRuntime.Cache.GetOrStore(“TagNamesOnly”,()=>\u TagRepository.Read().Select(t=>t.Name).OrderBy(t=>t.ToList());

GetOrStore的签名及其实现不包含对您发送的函数的求值。我真的不知道此刻发生了什么(或者它是否真的起作用)。您似乎正在将Func添加到缓存中

public const int DefaultCacheExpiration = 20;
private static readonly Object SyncRoot = new Object();
public static T GetOrStore<T>(this Cache cache, String key, Func<T> itemGenerator, Double expireInSeconds = DefaultCacheExpiration) {
    var item = cache[key];
    if (item != null)
        return (T)item;

    lock (SyncRoot) {
        // Fetch a second time to check if anyone have
        // added it while we blocked waiting for the lock.
        item = cache[key];
        if (item != null)
            return (T)item;

        // Invoke the almighty itemGenerator to execute,
        // and generate, the item that should be inserted
        // into the cache.
        item = itemGenerator.Invoke();
        cache.Insert(key, item, null, DateTime.Now.AddSeconds(expireInSeconds), Cache.NoSlidingExpiration);
        return (T)item;
    }
}

public static T GetOrStore<T>(this Cache cache, String key, T newItem, Double expireInSeconds = DefaultCacheExpiration) {
    return cache.GetOrStore(key, () => newItem, expireInSeconds);
}
public const int DefaultCacheExpiration=20;
私有静态只读对象SyncRoot=新对象();
public static T GetOrStore(此缓存、字符串键、Func itemGenerator、Double expireInSeconds=DefaultCacheExpirement){
var item=cache[key];
如果(项!=null)
退货(T)项;
锁定(同步根){
//再找一次来检查是否有人
//在我们阻止等待锁时添加了它。
项=缓存[键];
如果(项!=null)
退货(T)项;
//调用万能的itemGenerator执行,
//并生成应插入的项
//进入缓存。
item=itemGenerator.Invoke();
Insert(key,item,null,DateTime.Now.AddSeconds(expireInSeconds),cache.NoSlidingExpiration);
退货(T)项;
}
}
public static T GetOrStore(此缓存,字符串键,T newItem,Double expireInSeconds=DefaultCacheExpirement){
返回cache.GetOrStore(键,()=>newItem,expireInSeconds);
}

如果这样做不行,请查看您的asp.net缓存设置和服务器上的可用内存量。缓存在内存不足的情况下无法工作。

问题在于,您正在调用一个重载的方法来调用您的方法,正如@Simon Svensson指出的,您正在调用的方法不是您发布的方法。这是您实际调用的方法的C版本:

return cache.GetOrStore( key, generator != null ? generator() : default( T ), DefaultCacheExpiration )
您应该马上看到,如果第二个参数传递了非null值,它将调用
generator()

已更新

问题与缓存无关,而是您正在调用的重载方法正在执行lambda方法。如果您真的打算按照您概述的方式调用该方法,则必须将其更改为以下内容:

''# Fix StackOverflow Code Coloring Bug     
<Extension()>
Public Function GetOrStore(Of T)(ByVal cache As Cache, ByVal key As String, ByVal generator As Func(Of T)) As T
    ''# Null value to pass to first call. We can not use Nothing because VB can not infer the overload type
    Dim NV As Object = Nothing
    ''# Call the primary method passing a null value
    Dim Ret = cache.GetOrStore(key, NV, DefaultCacheExpiration)
    ''# If that call returns nothing call our generator() method and then re-call the main method
    If (Ret Is Nothing) AndAlso (generator IsNot Nothing) Then
        Ret = cache.GetOrStore(key, generator(), DefaultCacheExpiration)
    End If
    Return Ret
End Function
“”#修复StackOverflow代码着色错误
公共函数GetOrStore(Of T)(ByVal缓存作为缓存,ByVal键作为字符串,ByVal生成器作为Func(Of T))作为T
''#传递给第一个调用的空值。我们不能什么都不使用,因为VB不能推断重载类型
作为对象的Dim NV=无
''#调用传递空值的主方法
Dim Ret=cache.GetOrStore(key,NV,DefaultCacheExpiration)
''#如果该调用未返回任何内容,请调用我们的generator()方法,然后重新调用main方法
如果(Ret不为零)和(生成器不为零),则
Ret=cache.GetOrStore(key,generator(),DefaultCacheExpiration)
如果结束
回程网
端函数

我还没有测试过这个,但它或其他非常接近的东西应该会让你得到你想要的。这也是为什么我不是lambdas的超级粉丝。这个想法很好,但是人们倾向于将这么多的代码放在一起,并创建出不太可读的代码。我宁愿有10行可以读,而不是一行可以做同样的事情。

如果我在
上设置一个断点,那么实际上我也会从中提取代码。如果结果为空,那么
我可以看到结果=正是我需要的结果。我已经编辑了我的问题,以显示整个扩展方法。很抱歉,之前没有说得更清楚。您需要等待调用生成器,直到检查缓存是否不包含您的密钥。你新粘贴的代码包含几个重载,这些重载总是调用生成器。是的,就像我说的,我只是从另一篇文章中获取了一些代码。缓存是我很陌生的一个领域。对不起。缓存肯定是我需要解决的问题,因为我几乎迷路了。如果我在
GetOrStore
方法的
If(result==null)
行上粘贴断点,我可以看到
result
始终填充了正确的数据。因此,
生成器
正在生成正确的调用。这只是因为无论缓存是否正确,每次都会命中
\u TagRepository
''# Fix StackOverflow Code Coloring Bug     
<Extension()>
Public Function GetOrStore(Of T)(ByVal cache As Cache, ByVal key As String, ByVal generator As Func(Of T)) As T
    ''# Null value to pass to first call. We can not use Nothing because VB can not infer the overload type
    Dim NV As Object = Nothing
    ''# Call the primary method passing a null value
    Dim Ret = cache.GetOrStore(key, NV, DefaultCacheExpiration)
    ''# If that call returns nothing call our generator() method and then re-call the main method
    If (Ret Is Nothing) AndAlso (generator IsNot Nothing) Then
        Ret = cache.GetOrStore(key, generator(), DefaultCacheExpiration)
    End If
    Return Ret
End Function