using System; using System.Collections.Generic; using System.Text; using System.IO; using System.IO.IsolatedStorage; using System.Xml.Serialization; using System.Security.Permissions; namespace IndianHealthService.BMXNet.WinForm.Configuration { /// /// LocalPersistentStore is the core BMX implementation for the most common /// local setting store patterns: /// /// 1) In a special folder /// 2) In any specified path /// 3) In IsolatedStorage /// /// Use the object factory static class methods to create the different storage /// mechanisms. /// public class LocalPersistentStore : PersistentStore { private bool _attemptAncestorKeysOnRead = false; public bool AttemptAncestorKeysOnRead { get { return _attemptAncestorKeysOnRead; } set { _attemptAncestorKeysOnRead = value; } } public static LocalPersistentStore CreateIn(Environment.SpecialFolder aSpecialFolder, String subDirectoryPath,bool tryParentKeysOnRead) { LocalPersistentStore answer = new LocalPersistentStore(); answer.SpecialFolder = aSpecialFolder; answer.DirectoryPath = subDirectoryPath; answer.AttemptAncestorKeysOnRead = tryParentKeysOnRead; return answer; } public static LocalPersistentStore CreateIn(String aDirectoryPath, bool tryParentKeysOnRead) { LocalPersistentStore answer = new LocalPersistentStore(); answer.DirectoryPath = aDirectoryPath; answer.AttemptAncestorKeysOnRead = tryParentKeysOnRead; return answer; } protected static LocalPersistentStore CreateIn(IsolatedStorageScope aScope, bool tryParentKeysOnRead) { LocalPersistentStore answer = new LocalPersistentStore(); answer.IsolatedStorageScope = aScope; answer.AttemptAncestorKeysOnRead = tryParentKeysOnRead; return answer; } public static LocalPersistentStore CreateDefaultStorage(bool tryParentKeysOnRead) { return CreateIn(System.IO.IsolatedStorage.IsolatedStorageScope.User | System.IO.IsolatedStorage.IsolatedStorageScope.Assembly, tryParentKeysOnRead); } private Environment.SpecialFolder? _specialFolder = null; public Environment.SpecialFolder? SpecialFolder { get { return _specialFolder; } set { _specialFolder = value; } } private String _directoryPath = null; public String DirectoryPath { get { return _directoryPath; } set { _directoryPath = value; } } private IsolatedStorageScope? _isolatedStorageScope = null; public IsolatedStorageScope? IsolatedStorageScope { get { return _isolatedStorageScope; } set { _isolatedStorageScope = value; } } private T ReadFromFileSystem(String aDirectory, params string[] keys) { String path = Path.Combine(aDirectory, this.TranslateToValidFileName(keys)); T result = default(T); using (Stream stream = File.OpenRead(path)) { XmlSerializer serializer = new XmlSerializer(typeof(T)); result=(T)serializer.Deserialize(stream); } return result; } private void WriteToFileSystem(String aDirectory, T anObject, params string[] keys) { String path = Path.Combine(aDirectory, this.TranslateToValidFileName(keys)); if (!Directory.Exists(aDirectory)) { Directory.CreateDirectory(aDirectory); } using (Stream stream = File.Create(path)) { XmlSerializer serializer = new XmlSerializer(typeof(T)); serializer.Serialize(stream, anObject); } } /// /// Remove on non-letters, digits, to _ and add Bmx_ to the front. /// /// /// private string TranslateToValidFileName(params string[] keys) { StringBuilder builder = new StringBuilder(); builder.Append("bmx_"); foreach (String key in keys) { foreach (char each in key) { builder.Append((Char.IsLetterOrDigit(each)) ? each : '_'); } builder.Append("_"); } builder.Append("config.xml"); return builder.ToString(); } /// /// Isolated storage is scoped on user/application isolated storage /// /// /// private T ReadFromIsolatedStorage(params string[] keys) { T result = default(T); String validFileName = this.TranslateToValidFileName(keys) + ".is"; using (IsolatedStorageFile storage = IsolatedStorageFile.GetStore(this.IsolatedStorageScope.Value,null, null)) { using (Stream stream = new IsolatedStorageFileStream(validFileName, FileMode.Open, FileAccess.Read, storage)) { XmlSerializer serializer = new XmlSerializer(typeof(T)); result = (T)serializer.Deserialize(stream); } } return result; } /// /// Isolated storage is scoped on user/application isolated storage /// /// /// private void WriteToIsolatedStorage(T anObject, string[] keys) { String validFileName = this.TranslateToValidFileName(keys) + ".is"; using (IsolatedStorageFile storage = IsolatedStorageFile.GetStore(this.IsolatedStorageScope.Value, null,null)) { using (Stream stream = new IsolatedStorageFileStream(validFileName, FileMode.Create, FileAccess.Write, storage)) { XmlSerializer serializer = new XmlSerializer(typeof(T)); serializer.Serialize(stream,anObject); } } } public T Read(params string[] keys) { String[] keysToUse = keys; try { if (this.IsolatedStorageScope.HasValue) { return this.ReadFromIsolatedStorage(keysToUse); } else if (this.SpecialFolder.HasValue) { return this.ReadFromFileSystem(Path.Combine(Environment.GetFolderPath(this.SpecialFolder.Value),this.DirectoryPath), keysToUse); } else if (this.DirectoryPath != null) { return this.ReadFromFileSystem(this.DirectoryPath, keysToUse); } else { return default(T); } } catch { if (this.AttemptAncestorKeysOnRead && keysToUse.Length>1) { string[] newKeysToUse=new string[keysToUse.Length-1]; Array.Copy(keysToUse, newKeysToUse, keysToUse.Length - 1); return this.Read(newKeysToUse); } return default(T); } } public void Write(T anObject, params string[] keys) { if (this.IsolatedStorageScope.HasValue) { this.WriteToIsolatedStorage(anObject, keys); } else if (this.SpecialFolder.HasValue) { this.WriteToFileSystem(Path.Combine(Environment.GetFolderPath(this.SpecialFolder.Value),this.DirectoryPath), anObject, keys); } else if (this.DirectoryPath != null) { this.WriteToFileSystem(this.DirectoryPath, anObject, keys); } else { throw new Exception("Local persistent store not configured."); } } } }