3

所以我们有一个向客户端提供一些对象的 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;
        }
    }
4

1 回答 1

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”get,我也不会创建该值。

更干净的解决方案:

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();
    }
}
于 2012-06-08T11:37:18.633 回答