[英]How can I read/write app.config settings at runtime without using user settings?
[英].Net can app “B” read the user settings for app “A”?
标题说明了一切。 我在应用程序上定义了一些用户设置,这些设置最终由.NET存储在该应用程序的用户特定文件中。
我有一个密切相关的支持应用程序,需要读取其中一些相同的设置,但是我不知道这是否可以通过编程实现? 我看过的所有读取属性的示例都读取了与正在运行的应用程序关联的属性。
迈克尔
过去,我要做的就是将包含设置的xml文件保存到CommonApplicationSettings中。 然后,我拥有A和B都共享的通用C.dll
中的设置模型和读取器/写入器。
这是我制作的一个读写器的示例类。 每次在硬盘上更改文件时,它将设置保存在属性中,并且会加载新的设置副本并引发PropertyChanged
事件。
这两个程序都创建Configuration
的副本,然后侦听PropertyChanged
事件。 如果收到更改发生的信号,程序将从Configuration.Settings
重新读取设置,并将其用作活动值。
public sealed class Configuration : INotifyPropertyChanged, IDisposable
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(Configuration));
private readonly FileSystemWatcher _fileSystemWatcher;
public string SettingsPath { get; private set; }
private ConfigurationSettings _settings;
public Configuration()
{
const string settingsFileName = "Settings.xml";
const string programName = "App A";
SettingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), programName, settingsFileName);
if (!File.Exists(SettingsPath))
{
CreateDefaultFile();
}
//Read in the settings.
ReadSettingsFromFile();
_fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(SettingsPath), settingsFileName);
_fileSystemWatcher.BeginInit();
_fileSystemWatcher.Changed += FileSystemWatcherOnChanged;
_fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
_fileSystemWatcher.EndInit();
_fileSystemWatcher.EnableRaisingEvents = true;
}
public ConfigurationSettings Settings
{
get { return _settings; }
private set
{
if (Equals(value, _settings))
{
return;
}
_settings = value;
OnPropertyChanged("Settings");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void ReadSettingsFromFile()
{
Logger.Debug("Reading settings from the file.");
var serializer = new XmlSerializer(typeof(ConfigurationSettings));
using (FileStream settingsStream = File.Open(SettingsPath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
Settings = (ConfigurationSettings)serializer.Deserialize(settingsStream);
}
}
private async void FileSystemWatcherOnChanged(object sender, FileSystemEventArgs fileSystemEventArgs)
{
_fileSystemWatcher.EnableRaisingEvents = false;
Logger.Debug(new {fileSystemEventArgs.ChangeType, fileSystemEventArgs.FullPath, fileSystemEventArgs.Name});
//Add a pause to allow for the file to be finished writing.
await TaskEx.Delay(TimeSpan.FromSeconds(1));
ReadSettingsFromFile();
_fileSystemWatcher.EnableRaisingEvents = true;
}
/// <summary>
/// Creates the default settings file
/// </summary>
private void CreateDefaultFile()
{
var directoryInfo = Directory.CreateDirectory(Path.GetDirectoryName(SettingsPath));
//add rights for other users to modify the directory.
var security = directoryInfo.GetAccessControl();
security.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), FileSystemRights.Modify, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));
directoryInfo.SetAccessControl(security);
Settings = new ConfigurationSettings();
Save();
}
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public void Save()
{
bool oldState = false;
if (_fileSystemWatcher != null)
{
oldState = _fileSystemWatcher.EnableRaisingEvents;
}
try
{
//Disable events while the value is written.
if (_fileSystemWatcher != null)
{
_fileSystemWatcher.EnableRaisingEvents = false;
}
var serializer = new XmlSerializer(typeof(ConfigurationSettings));
using (var filestream = new FileStream(SettingsPath, FileMode.Create, FileAccess.Write, FileShare.None))
{
serializer.Serialize(filestream, Settings);
}
}
finally
{
if (_fileSystemWatcher != null)
{
_fileSystemWatcher.EnableRaisingEvents = oldState;
}
}
}
#region IDisposable Pattern
private bool _disposed;
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Finalizes this instance (called prior to garbage collection by the CLR)
/// </summary>
~Configuration()
{
Dispose(false);
}
private void Dispose(bool fromUserCode)
{
if (!_disposed)
{
if (fromUserCode)
{
if (_fileSystemWatcher != null)
{
_fileSystemWatcher.Dispose();
}
}
}
_disposed = true;
}
#endregion
}
这是我的ConfigurationSettings类的外观。
/// <summary>
/// Used as a container to represent the settings of the program
/// </summary>
[Serializable]
[XmlType(AnonymousType = false)]
public sealed class ConfigurationSettings : IEquatable<ConfigurationSettings>
{
private TimeSpan _uploadInterval;
private TimeSpan _pauseBetweenModules;
private static readonly TimeSpan UploadIntervalDefault = new TimeSpan(0, 0, 30, 0);
private static readonly TimeSpan PauseBetweenModulesDefault = new TimeSpan(0,0,0,5);
private const int InitialBatchSizeDefault = 100;
public ConfigurationSettings()
{
InitialBatchSize = InitialBatchSizeDefault;
UploadInterval = UploadIntervalDefault;
PauseBetweenModules = PauseBetweenModulesDefault;
DatabaseInstances = new ObservableCollection<DatabaseInstance>();
UploadPulseData = true;
}
/// <summary>
/// Will upload the pulse finical data
/// </summary>
public bool UploadPulseData { get; set; }
/// <summary>
/// The batch size the auto windowing function will use for its initial value for the upload module.
/// </summary>
public int InitialBatchSize { get; set; }
/// <summary>
/// The ammount of time a pause should be inserted between modules to allow the program to do any work that
/// has processing to do.
/// </summary>
[XmlIgnore] //Xml can not serialize a TimeSpan, so we use the hidden property PauseBetweenModulesInMilliseconds during serialization.
public TimeSpan PauseBetweenModules
{
get { return _pauseBetweenModules; }
set { _pauseBetweenModules = value; }
}
// Hidden property for serialization
[XmlElement("PauseBetweenModulesInMilliseconds")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public long PauseBetweenModulesInMilliseconds
{
get { return _pauseBetweenModules.Ticks / TimeSpan.TicksPerMillisecond; }
set { _pauseBetweenModules = new TimeSpan(value * TimeSpan.TicksPerMillisecond); }
}
/// <summary>
/// The length of time between upload batches.
/// </summary>
[XmlIgnore]
public TimeSpan UploadInterval
{
get { return _uploadInterval; }
set { _uploadInterval = value; }
}
// Hidden property for serialization
[XmlElement("UploadIntervalInMinutes")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public long UploadIntervalInMinutes
{
get { return _uploadInterval.Ticks / TimeSpan.TicksPerMinute; }
set { _uploadInterval = new TimeSpan(value * TimeSpan.TicksPerMinute);}
}
/// <summary>
/// The databases to run uploads against.
/// </summary>
public List<DatabaseInstance> DatabaseInstances { get; set; }
//We override Equals to make OnPropertyChanged less spammy, if the same file is loaded with the same settings it keeps the event from being raised.
public bool Equals(ConfigurationSettings other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return _uploadInterval.Equals(other._uploadInterval) &&
_pauseBetweenModules.Equals(other._pauseBetweenModules) &&
InitialBatchSize == other.InitialBatchSize &&
UploadPulseData == other.UploadPulseData &&
DatabaseInstances.SequenceEqual(other.DatabaseInstances);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj is ConfigurationSettings && Equals((ConfigurationSettings)obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = _uploadInterval.GetHashCode();
hashCode = (hashCode*397) ^ _pauseBetweenModules.GetHashCode();
hashCode = (hashCode*397) ^ InitialBatchSize;
hashCode = (hashCode*397) ^ UploadPulseData.GetHashCode();
if (DatabaseInstances != null)
{
foreach (var databaseInstance in DatabaseInstances)
{
hashCode = (hashCode * 397) ^ (databaseInstance != null ? databaseInstance.GetHashCode() : 0);
}
}
return hashCode;
}
}
}
使用ConfigurationManager.OpenExeConfiguration方法可以非常直接地读取另一个应用程序的设置。
例:
var config = System.Configuration.ConfigurationManager.OpenExeConfiguration(exePath);
var x = config.AppSettings.Settings["setting"].Value;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.