JD2022-TU1/main/tools/framework/JD.PropertyService/AutoSavingProperties.cs

129 lines
3.4 KiB
C#

using System;
using System.IO;
using System.Threading;
using JD.Kernel.Classes;
using JD.Kernel.StaticHelpers;
using JD.Serializers.Xml;
namespace JD.PropertyService
{
/// <summary>
/// Properties that load/save automatically to/from a file.
/// </summary>
internal class AutoSavingProperties : PropertiesWrapper, IDisposable
{
#region Variables
private static readonly TimeSpan AutoSavePeriod = TimeSpan.FromMinutes(5);
private readonly string m_filename;
private readonly Timer m_saveTimer;
private bool m_isDirty;
private readonly object m_saveLock = new object();
#endregion
#region Constructor
/// <summary>
/// Constructor.
/// </summary>
public AutoSavingProperties(string filename, IProperties wrappedProperties)
: base(wrappedProperties)
{
Throw.IfEmpty(filename, "filename");
Throw.IfNull(wrappedProperties, "wrappedProperties");
m_filename = filename;
string directory = Path.GetDirectoryName(m_filename);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
if (File.Exists(m_filename))
{
try
{
using (XmlSerializerReader reader = new XmlSerializerReader(File.OpenRead(filename)))
{
Wrapped.ReadFromXml(reader);
}
}
catch
{
Clear();
}
}
wrappedProperties.PropertyChanged += wrappedProperties_PropertyChanged;
m_saveTimer = new Timer(TimerCallback, null, AutoSavePeriod, AutoSavePeriod);
}
public void Dispose()
{
Wrapped.PropertyChanged -= wrappedProperties_PropertyChanged;
DisposableHelper.SafeDispose(m_saveTimer);
// Save it
Save();
}
#endregion
#region Methods
/// <summary>
/// Saves the properties to disk.
/// </summary>
public override bool Save()
{
if (m_isDirty)
{
lock (m_saveLock)
{
if (m_isDirty)
{
try
{
using (var stream = System.IO.File.OpenWrite(m_filename))
{
using (XmlSerializerWriter writer = new XmlSerializerWriter(stream))
{
m_isDirty = false;
Wrapped.WriteToXml(writer);
}
}
}
catch (Exception)
{
return false;
}
}
}
}
return true;
}
#endregion
#region Event Handlers
private void TimerCallback(object arg)
{
Save();
}
void wrappedProperties_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
m_isDirty = true;
}
#endregion
}
}