2010-08-10 71 views
1

我有一个类充满了属性。当访问属性时,它从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是关于不复制大部分代码的,有没有什么办法可以使这个工作自动完成?

+1

你确定你没有过早地优化它吗? – Marc 2010-08-10 13:02:45

+0

不,实际上我不是:P – 2010-08-10 14:07:50

回答

4

如前所述 “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中的属性并将值缓存在散列表中。提供一个属性访问器。

没有测试:

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); 
1

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

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