这是将数据加载到静态变量的可接受方式吗?

时间:2013-07-14 11:59:52

标签: c# .net static locking

我有一个类,它在实例化时会读取web.config文件。

我需要更改此逻辑,因此读取只发生一次(第一次创建实例),然后数据在生命周期内保持静态。

目前,I have this C# code

public AuthenticationProviderFactory()
{
    TraceManager = new Lazy<ITraceManager>(() => new TraceManager()).Value;

    AuthenticationProviders =
        new Lazy<IDictionary<string, IAuthenticationProvider>>(
            () => new Dictionary<string, IAuthenticationProvider>()).Value;

    Initialize();
}

没有什么可复杂的。创建字典然后初始化它。

为了简单起见(在这个问题中),我们只需说Initialize()只是从web.config文件中读取数据。从某处获取数据并将其粘贴到字典中。

现在我希望改变它,所以第一次创建这个类时,我创建一次字典(因此,它应该是静态的),然后将数据读入其中一次。

我在想这个但不确定这是否可以接受: -

private static Lazy<IDictionary<string, IAuthenticationProvider>> _authenticationProviders;
private static bool _hasParsedConfigFile = false;

public AuthenticationProviderFactory()
{
    TraceManager = new Lazy<ITraceManager>(() => new TraceManager()).Value;

    _authenticationProviders =
        new Lazy<IDictionary<string, IAuthenticationProvider>>(
            () =>
            {
                var authenticationProviders =
                    new Dictionary
                        <string, IAuthenticationProvider>();

                if (!_hasParsedConfigFile)
                {
                    Initialize();
                    _hasParsedConfigFile = true;
                }

                return authenticationProviders;
            });

    Initialize();
}

public static IDictionary<string, IAuthenticationProvider> AuthenticationProviders
{
    get { return _authenticationProviders.Value;  }
}

注意我是怎么想的,我更多地创造了懒惰的词典..懒惰:我还想知道这里的竞争条件是否会引起问题,我可能需要加倍-null锁定...但是听说双零锁定并不是非常好的螺纹安全/竞争条件,解决方案。

有人有什么建议吗?

1 个答案:

答案 0 :(得分:0)

我更喜欢在静态构造函数中初始化数据,这意味着您的代码将是

static AuthenticationProviderFactory()
{    
    AuthenticationProviders =
        new Lazy<IDictionary<string, IAuthenticationProvider>>(
            () => new Dictionary<string, IAuthenticationProvider>()).Value;

    Initialize();
}

但是这不会使用延迟加载,因为一旦访问类就会加载数据。

所以要使用延迟加载我建议使用如下的静态属性:

    private readonly object writeLock = new object();
    private static Lazy<IDictionary<string, IAuthenticationProvider>> _authenticationProviders;
    private static bool _hasParsedConfigFile = false;
    public static IDictionary<string, IAuthenticationProvider> AuthenticationProviders
    {
        get
        {
            if (!_hasParsedConfigFile)
            {
                lock (writeLock)
                {
                    if (!_hasParsedConfigFile)
                    {
                        _authenticationProviders = new Dictionary<string, IAuthenticationProvider>();
                        Initialize();
                        _hasParsedConfigFile = true;
                    }
                }
            }
            return _authenticationProviders;
        }
    }