mirror of
https://github.com/ckaczor/Common.git
synced 2026-01-13 17:22:40 -05:00
300 lines
10 KiB
C#
300 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.Configuration;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace Common.Settings
|
|
{
|
|
public class GenericSettingsProvider : SettingsProvider, IApplicationSettingsProvider
|
|
{
|
|
#region Member variables
|
|
|
|
private string _applicationName = string.Empty;
|
|
|
|
#endregion
|
|
|
|
#region Delegates
|
|
|
|
public delegate object OpenDataStoreDelegate();
|
|
public delegate void CloseDataStoreDelegate(object dataStore);
|
|
public delegate string GetSettingValueDelegate(object dataStore, string name, Version version);
|
|
public delegate void SetSettingValueDelegate(object dataStore, string name, Version version, string value);
|
|
public delegate List<Version> GetVersionListDelegate(object dataStore);
|
|
public delegate void DeleteSettingsForVersionDelegate(object dataStore, Version version);
|
|
|
|
#endregion
|
|
|
|
#region Callbacks
|
|
|
|
public OpenDataStoreDelegate OpenDataStore = null;
|
|
public CloseDataStoreDelegate CloseDataStore = null;
|
|
public GetSettingValueDelegate GetSettingValue = null;
|
|
public SetSettingValueDelegate SetSettingValue = null;
|
|
public GetVersionListDelegate GetVersionList = null;
|
|
public DeleteSettingsForVersionDelegate DeleteSettingsForVersion = null;
|
|
|
|
#endregion
|
|
|
|
#region SettingsProvider members
|
|
|
|
public override string ApplicationName
|
|
{
|
|
get { return _applicationName; }
|
|
set { _applicationName = value; }
|
|
}
|
|
|
|
public bool DeleteOldVersionsOnUpgrade { get; set; }
|
|
|
|
public override void Initialize(string name, NameValueCollection config)
|
|
{
|
|
if (string.IsNullOrEmpty(name))
|
|
name = GetType().Name;
|
|
|
|
base.Initialize(name, config);
|
|
}
|
|
|
|
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
|
|
{
|
|
// Create a new collection for the values
|
|
var values = new SettingsPropertyValueCollection();
|
|
|
|
// Get the current version number
|
|
var version = GetCurrentVersion();
|
|
|
|
// Open the data store
|
|
var dataStore = OpenDataStore();
|
|
|
|
// Loop over each property
|
|
foreach (SettingsProperty property in properties)
|
|
{
|
|
// Get the setting value for the current version
|
|
var value = GetPropertyValue(dataStore, property, version);
|
|
|
|
// Add the value to the collection
|
|
values.Add(value);
|
|
}
|
|
|
|
// Close the data store
|
|
CloseDataStore(dataStore);
|
|
|
|
return values;
|
|
}
|
|
|
|
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection properties)
|
|
{
|
|
// Get the current version number
|
|
var version = GetCurrentVersion();
|
|
|
|
// Open the data store
|
|
var dataStore = OpenDataStore();
|
|
|
|
// Loop over each property
|
|
foreach (SettingsPropertyValue propertyValue in properties)
|
|
{
|
|
// If the property isn't dirty or it is null then we can skip it
|
|
if (!propertyValue.IsDirty || (propertyValue.SerializedValue == null))
|
|
continue;
|
|
|
|
// Set the property value
|
|
SetPropertyValue(dataStore, propertyValue, version);
|
|
}
|
|
|
|
// Close the data store
|
|
CloseDataStore(dataStore);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Version numbers
|
|
|
|
private static Version GetCurrentVersion()
|
|
{
|
|
return Assembly.GetEntryAssembly().GetName().Version;
|
|
}
|
|
|
|
private Version GetPreviousVersion(object dataStore)
|
|
{
|
|
// Get the current version number
|
|
var currentVersion = GetCurrentVersion();
|
|
|
|
// Get a distinct list of version numbers
|
|
var versionList = GetVersionList(dataStore);
|
|
|
|
// Sort the list using the Version object and get the first value
|
|
var previousVersion = versionList.Where(v => v < currentVersion).OrderByDescending(v => v).FirstOrDefault();
|
|
|
|
return previousVersion;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Value get and set
|
|
|
|
private SettingsPropertyValue GetPropertyValue(object dataStore, SettingsProperty property, Version version)
|
|
{
|
|
// Create the value for the property
|
|
var value = new SettingsPropertyValue(property);
|
|
|
|
// Try to get the setting that matches the name and version
|
|
var setting = GetSettingValue(dataStore, property.Name, version);
|
|
|
|
// If the setting was found then set the value, otherwise leave as default
|
|
value.SerializedValue = setting;
|
|
|
|
// Value is not dirty since we just read it
|
|
value.IsDirty = false;
|
|
|
|
return value;
|
|
}
|
|
|
|
private void SetPropertyValue(object dataStore, SettingsPropertyValue value, Version version)
|
|
{
|
|
// Set the value for this version
|
|
SetSettingValue(dataStore, value.Property.Name, version, value.SerializedValue.ToString());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IApplicationSettingsProvider members
|
|
|
|
public void Reset(SettingsContext context)
|
|
{
|
|
// Get the current version number
|
|
var version = GetCurrentVersion();
|
|
|
|
// Open the data store
|
|
var dataStore = OpenDataStore();
|
|
|
|
// Delete all settings for this version
|
|
DeleteSettingsForVersion(dataStore, version);
|
|
|
|
// Close the data store
|
|
CloseDataStore(dataStore);
|
|
}
|
|
|
|
public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property)
|
|
{
|
|
// Open the data store
|
|
var dataStore = OpenDataStore();
|
|
|
|
// Get the previous version number
|
|
var previousVersion = GetPreviousVersion(dataStore);
|
|
|
|
SettingsPropertyValue value;
|
|
|
|
// If there is no previous version we have a return a setting with a null value
|
|
if (previousVersion == null)
|
|
{
|
|
// Create a new property value with the value set to null
|
|
value = new SettingsPropertyValue(property) { PropertyValue = null };
|
|
|
|
return value;
|
|
}
|
|
|
|
// Return the value from the previous version
|
|
value = GetPropertyValue(dataStore, property, previousVersion);
|
|
|
|
// Close the data store
|
|
CloseDataStore(dataStore);
|
|
|
|
return value;
|
|
}
|
|
|
|
public void Upgrade(SettingsContext context, SettingsPropertyCollection properties)
|
|
{
|
|
// Open the data store
|
|
var dataStore = OpenDataStore();
|
|
|
|
if (dataStore == null)
|
|
return;
|
|
|
|
// Get the previous version number
|
|
var previousVersion = GetPreviousVersion(dataStore);
|
|
|
|
// If there is no previous version number just do nothing
|
|
if (previousVersion == null)
|
|
return;
|
|
|
|
// Delete everything for the current version
|
|
Reset(context);
|
|
|
|
// Get the current version number
|
|
var currentVersion = GetCurrentVersion();
|
|
|
|
// Loop over each property
|
|
foreach (SettingsProperty property in properties)
|
|
{
|
|
// Get the previous value
|
|
var previousValue = GetPropertyValue(dataStore, property, previousVersion);
|
|
|
|
// Set the current value if there was a previous value
|
|
if (previousValue.SerializedValue != null)
|
|
SetPropertyValue(dataStore, previousValue, currentVersion);
|
|
}
|
|
|
|
if (DeleteOldVersionsOnUpgrade)
|
|
{
|
|
// Get a distinct list of version numbers
|
|
var versionList = GetVersionList(dataStore);
|
|
|
|
// Get everything before the current version
|
|
versionList = versionList.Where(v => v < currentVersion).ToList();
|
|
|
|
// Delete settings for anything in the list
|
|
foreach (var version in versionList)
|
|
DeleteSettingsForVersion(dataStore, version);
|
|
}
|
|
|
|
// Close the data store
|
|
CloseDataStore(dataStore);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Setting scope helpers
|
|
|
|
// ReSharper disable once UnusedMember.Local
|
|
private bool IsApplicationScoped(SettingsProperty property)
|
|
{
|
|
return HasSettingScope(property, typeof(ApplicationScopedSettingAttribute));
|
|
}
|
|
|
|
// ReSharper disable once UnusedMember.Local
|
|
private bool IsUserScoped(SettingsProperty property)
|
|
{
|
|
return HasSettingScope(property, typeof(UserScopedSettingAttribute));
|
|
}
|
|
|
|
private bool HasSettingScope(SettingsProperty property, Type attributeType)
|
|
{
|
|
// Check if the setting is application scoped
|
|
var isApplicationScoped = property.Attributes[typeof(ApplicationScopedSettingAttribute)] != null;
|
|
|
|
// Check if the setting is user scoped
|
|
var isUserScoped = property.Attributes[typeof(UserScopedSettingAttribute)] != null;
|
|
|
|
// Both user and application is not allowed
|
|
if (isUserScoped && isApplicationScoped)
|
|
throw new Exception("Setting cannot be both application and user scoped: " + property.Name);
|
|
|
|
// Must be set to either user or application
|
|
if (!isUserScoped && !isApplicationScoped)
|
|
throw new Exception("Setting must be either application or user scoped: " + property.Name);
|
|
|
|
// If we want to know if it is application scoped return that value
|
|
if (attributeType == typeof(ApplicationScopedSettingAttribute))
|
|
return isApplicationScoped;
|
|
|
|
// If we want to know if it is user scoped return that value
|
|
if (attributeType == typeof(UserScopedSettingAttribute))
|
|
return isUserScoped;
|
|
|
|
return false;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|