0

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

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

所以目前,我有这个 C# 代码

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

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

    Initialize();
}

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

为了简单起见(在这个 SO 问题中),我们只说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;  }
}

请注意我是如何认为我已经使 Lazy 字典的创建变得更加……懒惰:P 我还想知道这里的竞争条件是否会导致问题,并且我可能需要双空锁定……但听说过双空锁定不是一个很好的线程安全/竞争条件,解决方案。

有人有什么建议吗?

4

1 回答 1

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;
        }
    }
于 2013-07-14T12:45:36.177 回答