//******************************************************************************************************
// SettingsBase.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 01/30/2009 - J. Ritchie Carroll
// Generated original version of source code.
// 03/31/2009 - J. Ritchie Carroll
// Added code to allow override of name used to serialize field or property to configuration file
// by applying a SettingNameAttribute to the member.
// 04/01/2009 - J. Ritchie Carroll
// Added code to optionally encrypt settings based on EncryptSettingAttribute and to pickup
// DefaultValueAttribute value if provided and current value was uninitialized.
// 08/05/2009 - Josh L. Patterson
// Edited Comments.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 12/05/2010 - Pinal C. Patel
// Added Culture property that can be used for specifying a culture to use for value conversion
// and updated all value conversions to use the specified culture.
// 01/04/2011 - J. Ritchie Carroll
// Modified culture to default to InvariantCulture for English style parsing defaults.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using GSF.Reflection;
using GSF.Security.Cryptography;
namespace GSF.Configuration
{
///
/// Represents the base class for application settings that are synchronized with its configuration file.
///
///
/// In order to make custom types serializable for the configuration file, implement a for the type.
/// See MSDN for details.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class SettingsBase : IDisposable, IEnumerable, IEnumerable
{
#region [ Members ]
// Fields
private CultureInfo m_culture;
private BindingFlags m_memberAccessBindingFlags;
private bool m_requireSerializeSettingAttribute;
private bool m_disposed;
#endregion
#region [ Constructors ]
///
/// Creates a new instance of the class for the application's configuration file.
///
///
/// Assigns flag that determines if is required
/// to exist before a field or property is serialized to the configuration file.
///
protected SettingsBase(bool requireSerializeSettingAttribute)
{
m_culture = CultureInfo.InvariantCulture;
m_requireSerializeSettingAttribute = requireSerializeSettingAttribute;
m_memberAccessBindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
}
///
/// Releases the unmanaged resources before the object is reclaimed by .
///
~SettingsBase()
{
// If user failed to dispose class, we make sure settings get saved...
Dispose(false);
}
#endregion
#region [ Properties ]
///
/// Gets or sets the to use for the conversion of setting values to and from .
///
[Browsable(false), SerializeSetting(false)]
public CultureInfo Culture
{
get
{
return m_culture;
}
set
{
if ((object)value != null)
m_culture = value;
else
m_culture = CultureInfo.InvariantCulture;
}
}
///
/// Gets or sets used to access fields and properties of derived class.
///
///
/// Value defaults to | | .
///
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual BindingFlags MemberAccessBindingFlags
{
get
{
return m_memberAccessBindingFlags;
}
set
{
m_memberAccessBindingFlags = value;
}
}
///
/// Gets or sets flag that determines if is
/// required to exist before a field or property is serialized to the configuration
/// file; defaults to False.
///
[Browsable(false), SerializeSetting(false)]
public bool RequireSerializeSettingAttribute
{
get
{
return m_requireSerializeSettingAttribute;
}
set
{
m_requireSerializeSettingAttribute = value;
}
}
///
/// Gets or sets the value of the specified field or property.
///
/// Field or property name.
/// Value of setting.
/// This is the default member of this class.
public string this[string name]
{
get
{
return GetValue(name);
}
set
{
SetValue(name, value);
}
}
#endregion
#region [ Methods ]
///
/// Releases all the resources used by the object.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (!m_disposed)
{
try
{
// We'll make sure settings are saved when class is properly disposed...
if (disposing)
Save();
}
finally
{
m_disposed = true; // Prevent duplicate dispose.
}
}
}
///
/// Implementor should create setting in configuration file (or other location).
///
/// Field or property name, if useful (can be different from setting name).
/// Setting name.
/// Setting value.
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected abstract void CreateSetting(string name, string setting, string value);
///
/// Implementor should retrieve setting from configuration file (or other location).
///
/// Field or property name, if useful (can be different from setting name).
/// Setting name.
/// Setting value.
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected abstract string RetrieveSetting(string name, string setting);
///
/// Implementor should store setting to configuration file (or other location).
///
/// Field or property name, if useful (can be different from setting name).
/// Setting name.
/// Setting value.
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected abstract void StoreSetting(string name, string setting, string value);
///
/// Implementor should persist any pending changes to configuration file (or other location).
///
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected abstract void PersistSettings();
///
/// Gets setting name to use for specified field or property.
///
/// Field or property name.
/// applied to specified field or property; or if attribute does not exist.
///
/// Field or property name will be used for setting name unless user applied a
/// on the field or property to override name used to serialize value in configuration file.
///
/// cannot be null or empty.
public string GetSettingName(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("name cannot be null or empty");
return GetAttributeValue(name, name, attribute => attribute.Name).NotEmpty(name);
}
///
/// Gets the default value specified by , if any, applied to the specified field or property.
///
/// Field or property name.
/// Default value applied to specified field or property; or null if one does not exist.
/// cannot be null or empty.
public object GetDefaultValue(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("name cannot be null or empty");
return GetAttributeValue(name, null, attribute => attribute.Value);
}
///
/// Gets the encryption status specified by , if any, applied to the specified field or property.
///
/// Field or property name.
/// Encryption status applied to specified field or property; or false if one does not exist.
/// cannot be null or empty.
public bool GetEncryptStatus(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("name cannot be null or empty");
return GetAttributeValue(name, false, attribute => attribute.Encrypt);
}
///
/// Gets the optional private encryption key specified by , if any, applied to the specified field or property.
///
/// Field or property name.
/// Encryption private key applied to specified field or property; or null if one does not exist.
/// cannot be null or empty.
public string GetEncryptKey(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentException("name cannot be null or empty");
return GetAttributeValue(name, null, attribute => attribute.PrivateKey).NotEmpty(name);
}
///
/// Adds a setting to the application's configuration file, if it doesn't already exist.
///
/// Field or property name.
/// Setting value.
///
/// Use this function to ensure a setting exists, it will not override an existing value.
///
public void CreateValue(string name, object value)
{
string setting = GetSettingName(name);
if ((object)value == null)
CreateSetting(name, setting, EncryptValue(name, setting, ""));
else
CreateSetting(name, setting, EncryptValue(name, setting, Common.TypeConvertToString(value, m_culture)));
}
///
/// Copies the given value into the specified application setting.
///
/// Field or property name.
/// Setting value.
public void SetValue(string name, object value)
{
string setting = GetSettingName(name);
if ((object)value == null)
StoreSetting(name, setting, EncryptValue(name, setting, ""));
else
StoreSetting(name, setting, EncryptValue(name, setting, Common.TypeConvertToString(value, m_culture)));
}
///
/// Gets the application's configuration file setting converted to the given type.
///
/// Type to use for setting conversion.
/// Field or property name.
/// Value of specified configuration file setting converted to the given type.
public T GetValue(string name)
{
string setting = GetSettingName(name);
return DecryptValue(name, setting, RetrieveSetting(name, setting)).ConvertToType(null, m_culture);
}
///
/// Gets the application's configuration file setting converted to the given type.
///
/// Field or property name.
/// Setting type.
/// Value of specified configuration file setting converted to the given type.
public object GetValue(string name, Type type)
{
string setting = GetSettingName(name);
return DecryptValue(name, setting, RetrieveSetting(name, setting)).ConvertToType