【问题标题】:'caching' properties“缓存”属性
【发布时间】:2011-03-27 19:41:29
【问题描述】:

我有一个充满属性的类。当访问属性时,它会从 XDocument 中读取一些值。

public class Foo
{
 private XDocument root;

 public Foo(Stream str)
 {
  root = XDocument.load(str);
 }

 public String Bar
 {
  get
  {
   return root.Element("bar").Value;
  }
 }

}

只是看起来有点开销,因为每次访问它都必须再次读取 XDocument。我尝试将其“缓存”如下

public String Bar
{
 get
 {
  if(String.IsNullOrEmpty(this.Bar))
   return root.Element("bar").Value;
  else
   return this.Bar;
 }
}

这对我来说似乎很不错,只是我有一个问题。该类具有大约 200 个属性。每次我必须做这个检查,因为 OOP 就是不复制大部分代码,有什么方法可以自动完成这项工作吗?

【问题讨论】:

标签: c# caching properties


【解决方案1】:

正如“thelost”所提到的,每个属性都没有一个字段。保留字典作为缓存,因此您无需为未访问的属性支付任何费用。

我建议你有一个方法,你可以提供检索真实值的机制。例如:

public class Foo
{
    private enum CacheKey
    {
        Bar, Baz, ...;
    }

    private readonly XDocument doc;
    private readonly Dictionary<CacheKey, string> cache;

    private string Fetch(CacheKey key, Func<XDocument, string> computation)
    {
        string result;
        if (!cache.TryGetValue(key, out result))
        {
            result = computation(doc);
            cache[key] = result;
        }
        return result;
    }

    public string Bar
    {
        get { return Fetch(CacheKey.Bar, doc => doc.Element("bar").Value); }
    }
}

这样每个属性最终都相当紧凑 - 它基本上表达了所涉及的缓存键,以及如何计算属性。如果您需要不同类型的属性,您可能希望缓存只有TValueobject,并使Fetch 方法通用,必要时进行强制转换。诚然,这最终会变成装箱值类型。

如果您在多个地方使用此方法,您可能希望创建一个通用的ComputingCache 类以避免重复逻辑。

【讨论】:

    【解决方案2】:

    将属性保存在枚举中并将值缓存在哈希表中。提供单个属性访问器。

    未测试:

    enum MyProperties {
        Prop1,
        Prop2
    }
    
    // ...
    
    static class PropertyProvider {
        static Hashtable<MyProperties, Object> cache = new Hashtable<MyProperties, Object>();
        static Object getProperty(MyProperties prop) {
            if (!cache.ContainsKey(prop)) {
                cache.add(prop, "SOMETHING");
            }
    
            return cache[prop];
        }
    }
    
    // ...
    
    Object result = PropertyProvider.getProperty(MyProperties.Prop1);
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 .NET 4.0,则可以使用方便的 Lazy 类。

      http://weblogs.asp.net/gunnarpeipman/archive/2009/05/19/net-framework-4-0-using-system-lazy-lt-t-gt.aspx

      如果您使用的是以前版本的框架,您可以编写自己的 Lazy 类版本(这不是特别复杂)。

      【讨论】:

      • 每个属性仍然会得到一个字段,这听起来像是 OP 不想要的。
      【解决方案4】:

      懒惰的部分重要吗?如果没有,只需在 ctor 时间填充所有属性(它们都可以是自动的),你就完成了。我宁愿这样做,因为如果 xml 有问题,它会更快地失败。如果惰性很重要,那么在 .NET 4 中您可以为它们使用惰性。

      请注意,无论您使用哪种缓存方法,请确保 1) 您的 getter 中没有堆栈溢出问题,以及 2) 空值/缺失值仍然被认为对于填充缓存条目是有效的(如果对于源xml)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-09
        • 1970-01-01
        • 2013-01-28
        • 2011-07-05
        • 2020-12-29
        • 2013-05-02
        • 2011-07-16
        • 1970-01-01
        相关资源
        最近更新 更多