更改经典单例以用于 .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.DataSouceSettings
与 sp.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)
我有以下 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);
}
我通过
配置 DIvar 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.DataSouceSettings
与 sp.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)