更改经典单例以用于 .NET Core 3.1 和 DependencyInjection (DI)

Changing a Classic Singleton for use with .NET Core 3.1 and DependencyInjection (DI)

我有以下 class 我想在 .NET Core 中使用 DI

public class DefaultSettingsProvider : ISettingsProvider
{
    private static DefaultSettingsProvider _instance = null;
    private string _fileName = "blundergat.settings";

    private DefaultSettingsProvider() { }

    public static DefaultSettingsProvider Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new DefaultSettingsProvider();
                if (File.Exists(_instance.GetSerializedFilePath()))
                {
                    DefaultSettingsProvider o = _instance.Deserialize();
                    _instance = o ?? _instance;
                }
                _instance.RestoreDefaults();
            }
            return _instance;
        }
    }

    public void Save()
    {
        (this as ICustomXmlSerializableObject).Serialize();
    }

    public string GetSerializedFilePath()
    {
        return Path.Combine(Environment.CurrentDirectory, _fileName);
    }

    public void RestoreDefaults(bool force = false)
    {
        if (DataSourceSettings == null || force)
            DataSourceSettings = new DataSourceSettings();

        if (IcpSolverSettings == null || force)
            IcpSolverSettings = new IcpSolverSettings();
    }

    [XmlElement, Browsable(false)]
    public DataSourceSettings DataSourceSettings { get; set; }

    [XmlElement, Browsable(false)]
    public IcpSolverSettings IcpSolverSettings { get; set; }
}

public interface ISettingsProvider : ICustomXmlSerializableObject
{
    void Save();

    void RestoreDefaults(bool force = false);
}

我通过

配置 DI
var serviceProvider = new ServiceCollection()
    .AddSingleton<IHostedService, CoreHostingService>()
    .AddSingleton<ISolverManagementService, SolverManagementService>()
    .AddSingleton<IDepthMapToPointCloudAdapter, DepthMapToPointCloudAdapter>()
    .AddSingleton<IIcpBatchSolverService, IcpBatchSolverService>()
    .AddSingleton<ISettingsProvider, DefaultSettingsProvider>()
    .AddLogging(builder =>
    {
        builder.SetMinimumLevel(LogLevel.Trace); 
        builder.AddSerilog(Log.Logger);
    })
    .BuildServiceProvider();

这显然无法满足我的要求,因此我尝试将 class 更改为

public class DefaultSettingsProvider : ISettingsProvider
{
    private static DefaultSettingsProvider instance = null;
    private string _fileName = "blundergat.settings";

    public DefaultSettingsProvider()
    {
        if (instance == null)
        {
            instance = this;
            if (File.Exists(instance.GetSerializedFilePath()))
            {
                DefaultSettingsProvider o = instance.Deserialize();
                instance = o ?? instance;
            }
            instance.RestoreDefaults();
        }
    }

    public void Save()
    {
        (this as ICustomXmlSerializableObject).Serialize();
    }

    public string GetSerializedFilePath()
    {
        return Path.Combine(Environment.CurrentDirectory, _fileName);
    }

    public void RestoreDefaults(bool force = false)
    {
        if (DataSourceSettings == null || force)
            DataSourceSettings = new DataSourceSettings();

        if (IcpSolverSettings == null || force)
            IcpSolverSettings = new IcpSolverSettings();
    }

    [XmlElement, Browsable(false)]
    public DataSourceSettings DataSourceSettings { get; set; }

    [XmlElement, Browsable(false)]
    public IcpSolverSettings IcpSolverSettings { get; set; }
}

这适用于 DI,但是,由于我使用的是静态“实例”,因此无法正确初始化设置,因此当我尝试这样做时

public A(ISettingsProvider sp)
{
    string someSetting = sp.DataSouceSettings.DataPath;
}   

DataSouceSettings 为空,因为它未初始化。如何将 instance.DataSouceSettingssp.DataSouceSettings 对齐?从本质上讲,我如何修改此 class 以使用 DI,同时又能像使用 classic 单例模式那样操作?

Ps。为了完整起见。

[Serializable]
public class DataSourceSettings
{
    public DataSourceSettings()
    {
        BaseDirectory = String.Empty;
    }

    [XmlElement, Browsable(false)]
    public string BaseDirectory { get; set; }
}

因为你已经有了一个单例实例,只需添加它而不是让 DI 管理新实例的生命周期 - AddService:

  .AddSingleton<ISettingsProvider>(DefaultSettingsProvider.Instance)