所以我们有一个WCF服务,它为客户端提供了一些对象。我们的wcf服务从数据访问层(DAL)获取数据。 DAL从API获取数据并将其格式化为我们可以使用的对象。对于大多数对象来说,这很有效。
但我们还需要API中的对象列表,并且对象不会更改。针对API的查询需要15到20秒。对于相同的数据,多次运行此查询的方法。 所以我们想将列表存储在内存中。因为DBA不是我们最好的朋友,所以不能选择SQLite或SQL CE。
现在我们有这样的东西,第一次加载组时我们将它们存储在私有静态变量中。 这是做这样的事情的正确方法,还是有更好的方法?
public static class GroupStore
{
private static DTO.Group[] _groups;
public static DTO.Group[] GetAll()
{
if (_groups == null)
{
var dal = PluginHandler.Instance.GetPlugin();
_groups = dal.GetAll();
}
return _groups;
}
}
答案 0 :(得分:4)
如果您使用的是.NET4,则可以使用Lazy<T>
类。它是线程安全的,并为您包装延迟加载。
代码变得更加干净:
public static class GroupStore
{
private static Lazy<DTO.Group[]> _groups = new Lazy<DTO.Group[]>(GetAll);
public static DTO.Group[] Groups { get { return _groups.Value; } }
private static DTO.Group[] GetAll()
{
var dal = PluginHandler.Instance.GetPlugin();
return dal.GetAll();
}
}
<强>更新强>
您在评论中链接的答案是可以的。但IsValueCreated
无理由地使用锁定(因为列表可能在检查和下一次访问之间发生了变化)。
如果调用“ToString”,我也不会创建值。
更清洁的解决方案:
public sealed class Lazy<T> where T : class
{
private readonly object _syncRoot = new object();
private readonly Func<T> _factory;
private T _value;
public Lazy(Func<T> factory)
{
if (factory == null) throw new ArgumentNullException("factory");
_factory = factory;
}
public T Value
{
get
{
if (_value == null)
{
lock (_syncRoot)
{
if (_value == null)
{
_value = _factory();
}
}
}
return _value;
}
}
public override string ToString()
{
return _value == null ? "Not created" : _value.ToString();
}
}