2012-01-26 233 views
1

这里的缓存返回值是什么这会是什么样子,如果我可以修改有问题的类伪代码扩展方法

public class Foo 
{ 
    private TheDataType _Data; 
    public TheDataType GetData() 
    { 
     if (_Data != null) 
      return _Data; 

     // fetch/generate data 

     return _Data; 
    } 
} 

我如何把它变成一个扩展方法?该_Data的定义/范围是什么困扰着我......

================================ ================

这可能是最接近我想要什么,但觉得像这么简单的东西矫枉过正

public static class FooExtensions 
{ 
    private static ConcurrentDictionary<Foo,TheDataType> DataCache = new ConcurrentDictionary<Foo,TheDataType>(); 
    public static TheDataType GetData(this Foo foo) 
    { 
     TheDataType data; 
     if (DataCache.TryGetValue(foo, out data)) 
      return data 

     // fetch/generate data 

     DataCache.Add(foo, data); 
     return data; 
    } 
} 
+0

能否请你更具体?你想要延续什么课程?这可能是“你想使用扩展方法,因为它们很酷,但你真的不需要扩展方法”。 – qJake

+0

@SpikeX我只想要一个简单的实例级高速缓存,用于执行某些邪恶并经常被称为安静的方法。 –

回答

2

你可以有你扩展方法,其利用保持基于针对所述实例一些唯一标识符道中的数据的高速缓存管理器类(自定义或内置于框架):

public static DataType GetData(this Foo obj) 
{ 
    DataType retVal; 

    // this sample doesn't show any locking, i.e. it is not thread safe 

    // if cache manager contains data return from there 
    if(CacheManager.HasData(obj.UniqueId)) 
    { 
     retVal = CacheManager.GetData(obj.UniqueId); 
    }  
    else 
    { 
     // otherwise invoke a method on obj and add to cache 
     retVal = obj.GetData(); 
     CacheManager.Add(obj.UniqueId, retVal); 
    } 

    return retVal; 
} 

然而,这在我看来是一个扩展方法的可能被滥用,即使它的语法干净。这将取决于其使用的环境以及副作用的明显程度。例如,这将是非常艰难的另一家开发商解决,如果他们不知道的GetData()使用高速缓存,缓存过期不清晰等

+0

我实际上要使用'ConcurrentDictionary'来防止我想要的东西不可能,这听起来就像是这样。尽管努力肯定是+1。 –

0

我不太清楚你是什么试图完成,但如果我遵循,它会看起来像。

public static class FlargExtensions 
{ 
    private static Flarg flarg; 

    public static Flarg GetData(this Flarg flarg) 
    { 
     if (FlargExtensions.flarg != null) 
      return Class1.flarg; 

     FlargExtensions.flarg = new Flarg(); 
     return FlargExtensions.flarg; 
    } 
} 

public class Flarg 
{ 
} 
+2

几乎可以肯定的是,OP想要在* instance *级别缓存,而不是在静态上下文中缓存。 –

+0

这很有可能。但是,OP的意图并不明确。在这种情况下,示例用例比类定义更有用。 –

1

这是一个很好的功能缓存,描述在this blog post of mine。我们的想法是把一个函数用一个参数,使之成为其缓存原来的结果另一个功能:

public static Func<TKey, TValue> Cached<TKey, TValue>(this Func<TKey, TValue> valueFunction) 
{ 
    var cache = new Dictionary<TKey, TValue>(); 

    return key => 
    { 
     TValue value; 

     if(!cache.TryGetValue(key, out value)) 
     { 
      value = valueFunction(key); 

      cache[key] = value; 
     } 

     return value; 
    }; 
} 

缓存字典被嵌入返回的闭包,所以将有相同的寿命我们返回的函数。

你会用它替换原来的调用来获取新功能的数据:

public class UsesTheDataType 
{ 
    private readonly Func<Foo, TheDataType> _generateData; 

    public UsesTheDataType() 
    { 
     _generateData = GenerateData; 

     _generateData = _generateData.Cached(); 
    } 

    public void UseTheDataType(Foo foo) 
    { 
     var theDataType = _generateData(foo); 

     // theDataType is either a new value or cached value 
    } 

    private TheDataType GenerateData(Foo foo) 
    { 
     // Only called the first time for each foo 
    } 
} 

这里的好处是,该高速缓存的所有功能写一次,因此可以重用无论您需要缓存什么,都采用相同的方法。这也避免了由于使用静态缓存而导致的可能的内存泄漏。

这也可以在一个线程安全的方式来完成。请参阅second post in the series进行演练。