【问题标题】:Changing a Classic Singleton for use with .NET Core 3.1 and DependencyInjection (DI)更改经典单例以与 .NET Core 3.1 和 DependencyInjection (DI) 一起使用
【发布时间】:2020-01-10 00:40:24
【问题描述】:

我有以下类,我想在带有 DI 的 .NET Core 中使用它

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();

这显然不能按我的要求工作,所以我试图将类更改为这个

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 为 null,因为它未初始化。如何将instance.DataSouceSettingssp.DataSouceSettings 对齐?本质上,我怎样才能修改这个类以使用 DI,同时又能像使用经典单例模式那样操作?

附言。为了完整性。

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

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

【问题讨论】:

  • 您已经将它作为单例添加到 DI,所以我认为在类实现中保留单例代码没有意义。

标签: c# singleton settings


【解决方案1】:

由于您已经有一个单例实例,只需添加它,而不是让 DI 管理新实例的生命周期 - AddService

  .AddSingleton<ISettingsProvider>(DefaultSettingsProvider.Instance)

【讨论】:

  • 啊,这么简单。感谢您的宝贵时间。
  • 这将强制在启动过程中创建实例。如果你想推迟它; .AddSingleton&lt;ISettingsProvider&gt;(p =&gt; DefaultSettingsProvider.Instance)
  • 使用 Mocks (Moq) 但没有无参数 ctor 进行单元测试的最佳方法是什么?
猜你喜欢
  • 1970-01-01
  • 2020-09-04
  • 1970-01-01
  • 2023-04-07
  • 2022-06-30
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多