Last active
October 21, 2018 12:51
-
-
Save mrozema/39d5a61fa0984168f69c7bb0190716ab to your computer and use it in GitHub Desktop.
PersistentStorage Xamarin implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
namespace PersistentStorage | |
{ | |
public interface IPersistentStorage | |
{ | |
IEnumerable<string> Groups { get; } | |
IEnumerable<string> KeysForGroup(string group); | |
bool ContainsKey(string group, string key); | |
T Get<T>(string group, string key, T defaultValue) where T : new(); | |
string Get(string group, string key, string defaultValue); | |
string Get(string group, string key); | |
T Get<T>(string group, string key) where T : new(); | |
IEnumerable<T> GetAll<T>(string group, string key) where T : new(); | |
IEnumerable<string> GetAll(string group, string key); | |
void Set<T>(string group, string key, T value) where T : new(); | |
void Set(string group, string key, string value); | |
void SetAll<T>(string group, string key, IEnumerable<T> value) where T : new(); | |
void SetAll(string group, string key, IEnumerable<string> value); | |
void Delete(string group, string key); | |
Dictionary<string, T> GetGroup<T>(string group) where T : new(); | |
Dictionary<string, string> GetGroup(string group); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace PersistenStorage | |
{ | |
public class PersistentStorage : IPersistentStorage | |
{ | |
ConcurrentDictionary<string, List<string>> groupMappings = new ConcurrentDictionary<string, List<string>>(); | |
public SimpleStorage() | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup("schema"); | |
var groups = grp.Get<string[]>("groups"); | |
if (groups == null) { | |
Console.WriteLine("Groups was null when initializing SimpleStorage"); | |
} else if (groups.Any()) { | |
foreach (var storageGroup in groups) { | |
var keyStorage = PerpetualEngine.Storage.SimpleStorage.EditGroup($"{storageGroup}Keys"); | |
var keys = keyStorage.Get<string[]>("keys"); | |
groupMappings.TryAdd(storageGroup, keys.ToList()); | |
} | |
} | |
} | |
public IEnumerable<string> Groups => groupMappings.Keys; | |
public bool ContainsKey(string group, string key) | |
{ | |
var keys = new List<string>(); | |
if (groupMappings.TryGetValue(group, out keys)) { | |
return keys.Contains(key); | |
} | |
return false; | |
} | |
public void Delete(string group, string key) | |
{ | |
TryRemoveGroupAndKey(group, key); | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
grp.Delete(key); | |
} | |
public string Get(string group, string key) | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
return grp.Get(key); | |
} | |
public string Get(string group, string key, string defaultValue) | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
return grp.Get(key, defaultValue); | |
} | |
public T Get<T>(string group, string key) where T : new() | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
return grp.Get<T>(key); | |
} | |
public T Get<T>(string group, string key, T defaultValue) where T : new() | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
return grp.Get<T>(key, defaultValue); | |
} | |
IEnumerable<T> IPersistentStorage.GetAll<T>(string group, string key) | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
return grp.Get<T[]>(key); | |
} | |
public IEnumerable<string> GetAll(string group, string key) | |
{ | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
return grp.Get<string[]>(key); | |
} | |
public void Set(string group, string key, string value) | |
{ | |
TryAddGroupAndKey(group, key); | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
grp.Put(key, value); | |
} | |
public void Set<T>(string group, string key, T value) where T : new() | |
{ | |
TryAddGroupAndKey(group, key); | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
grp.Put<T>(key, value); | |
} | |
public void SetAll<T>(string group, string key, IEnumerable<T> values) where T : new() | |
{ | |
TryAddGroupAndKey(group, key); | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
grp.Put(key, values.ToArray()); | |
} | |
public void SetAll(string group, string key, IEnumerable<string> values) | |
{ | |
TryAddGroupAndKey(group, key); | |
var grp = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
grp.Put(key, values.ToArray()); | |
} | |
public Dictionary<string, T> GetGroup<T>(string group) where T : new() | |
{ | |
var dictionary = new Dictionary<string, T>(); | |
var storage = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
var keys = KeysForGroup(group); | |
if (keys != null && keys.Any()) { | |
foreach (var key in keys) { | |
var valueForKey = storage.Get<T>(key); | |
dictionary.Add(key, valueForKey); | |
} | |
} | |
return dictionary; | |
} | |
public Dictionary<string, string> GetGroup(string group) | |
{ | |
var dictionary = new Dictionary<string, string>(); | |
var storage = PerpetualEngine.Storage.SimpleStorage.EditGroup(group); | |
var keys = KeysForGroup(group); | |
if (keys != null && keys.Any()) { | |
foreach (var key in keys) { | |
var valueForKey = storage.Get(key); | |
dictionary.Add(key, valueForKey); | |
} | |
} | |
return dictionary; | |
} | |
void TryRemoveGroupAndKey(string group, string key) | |
{ | |
var keys = new List<string>(); | |
if (groupMappings.TryGetValue(group, out keys)) { | |
keys.Remove(key); | |
PerpetualEngine.Storage.SimpleStorage.EditGroup($"{group}Keys").Put("keys", keys.ToArray()); | |
} | |
} | |
void TryAddGroupAndKey(string group, string key) | |
{ | |
var existingKeys = new List<string>(); | |
if (groupMappings.TryGetValue(group, out existingKeys)) { | |
if (!existingKeys.Contains(key)) { | |
if (key != null) { | |
existingKeys.Add(key); | |
PerpetualEngine.Storage.SimpleStorage.EditGroup($"{group}Keys").Put("keys", existingKeys.ToArray()); | |
} | |
} | |
} else { | |
var newKeys = new List<string> { key }; | |
groupMappings.TryAdd(group, newKeys); | |
PerpetualEngine.Storage.SimpleStorage.EditGroup("schema").Put("groups", groupMappings.Select(g => g.Key).ToArray()); | |
PerpetualEngine.Storage.SimpleStorage.EditGroup($"{group}Keys").Put("keys", newKeys.ToArray()); | |
} | |
} | |
public IEnumerable<string> KeysForGroup(string group) | |
{ | |
var keys = new List<string>(); | |
if (groupMappings.TryGetValue(group, out keys)) { | |
return keys; | |
} | |
return new List<string>(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Runtime.Serialization.Formatters.Binary; | |
namespace TestStorage | |
{ | |
public class TestStorage : IPersistentStorage | |
{ | |
Dictionary<string, Dictionary<string, string>> storage = new Dictionary<string, Dictionary<string, string>>(); | |
Dictionary<string, Dictionary<string, List<string>>> listStorage = new Dictionary<string, Dictionary<string, List<string>>>(); | |
public IEnumerable<string> Groups => storage.Keys.Concat(listStorage.Keys); | |
public bool ContainsKey(string group, string key) { | |
return storage.ContainsKey(group) && storage[group].ContainsKey(key); | |
} | |
public void Delete(string group, string key) { | |
if (storage.ContainsKey(group)) { | |
storage[group].Remove(key); | |
} | |
} | |
public IEnumerable<T> GetAll<T>(string group, string key) where T : new() | |
{ | |
if (listStorage.ContainsKey(group)) { | |
var grp = listStorage[group]; | |
if (grp.ContainsKey(key)) { | |
var val = grp[key]; | |
return val.Select(v => DeserializeObject<T>(v)); | |
} | |
} | |
return new List<T>(); | |
} | |
public IEnumerable<string> GetAll(string group, string key) { | |
if (listStorage.ContainsKey(group)) { | |
var grp = listStorage[group]; | |
if (grp.ContainsKey(key)) { | |
return grp[key]; | |
} | |
} | |
return new List<string>(); | |
} | |
public string Get(string group, string key) { | |
if (storage.ContainsKey(group)) { | |
var grp = storage[group]; | |
if (grp.ContainsKey(key)) { | |
return grp[key]; | |
} | |
} | |
return null; | |
} | |
public string Get(string group, string key, string defaultValue) { | |
if (storage.ContainsKey(group)) { | |
var grp = storage[group]; | |
if (grp.ContainsKey(key)) { | |
return grp[key]; | |
} | |
} | |
return defaultValue; | |
} | |
public T Get<T>(string group, string key) where T : new() { | |
if (storage.ContainsKey(group)) { | |
var grp = storage[group]; | |
if (grp.ContainsKey(key)) { | |
var val = DeserializeObject<T>(grp[key]); | |
return val; | |
} | |
} | |
return default(T); | |
} | |
public T Get<T>(string group, string key, T defaultValue) where T : new() { | |
if (storage.ContainsKey(group)) { | |
var grp = storage[group]; | |
if (grp.ContainsKey(key)) { | |
var val = grp[key]; | |
return DeserializeObject<T>(val); | |
} | |
} | |
return defaultValue; | |
} | |
public void Set(string group, string key, string value) { | |
if (storage.ContainsKey(group)) { | |
var grp = storage[group]; | |
if (grp.ContainsKey(key)) { | |
grp[key] = value; | |
} | |
else { | |
grp.Add(key, value); | |
} | |
} | |
else { | |
var data = new Dictionary<string, string> { { key, value } }; | |
storage.Add(group, data); | |
} | |
} | |
public void Set<T>(string group, string key, T value) where T : new() { | |
var serialized = SerializeObject<T>(value); | |
if (storage.ContainsKey(group)) { | |
var grp = storage[group]; | |
if (grp.ContainsKey(key)) { | |
grp[key] = serialized; | |
} | |
else { | |
grp.Add(key, serialized); | |
} | |
} | |
else { | |
var data = new Dictionary<string, string> { { key, serialized } }; | |
storage.Add(group, data); | |
} | |
} | |
public void SetAll<T>(string group, string key, IEnumerable<T> values) where T : new() { | |
var serialized = values.Select(v => SerializeObject<T>(v)).ToList(); | |
if (listStorage.ContainsKey(group)) { | |
var grp = listStorage[group]; | |
if (grp.ContainsKey(key)) { | |
grp[key] = serialized; | |
} | |
else { | |
grp.Add(key, serialized); | |
} | |
} | |
else { | |
listStorage.Add(group, new Dictionary<string, List<string>> { { key, serialized } }); | |
} | |
} | |
public void SetAll(string group, string key, IEnumerable<string> values) { | |
if (listStorage.ContainsKey(group)) { | |
var grp = listStorage[group]; | |
if (grp.ContainsKey(key)) { | |
grp[key] = values.ToList(); | |
} | |
else { | |
grp.Add(key, values.ToList()); | |
} | |
} | |
else { | |
listStorage.Add(group, new Dictionary<string, List<string>> { { key, values.ToList() } }); | |
} | |
} | |
internal string SerializeObject<T>(T o) where T : new() { | |
using (var stream = new MemoryStream()) { | |
new BinaryFormatter().Serialize(stream, o); | |
return Convert.ToBase64String(stream.ToArray()); | |
} | |
} | |
// taken from http://stackoverflow.com/questions/2861722/binary-serialization-and-deserialization-without-creating-files-via-strings | |
internal T DeserializeObject<T>(string str) where T : new() { | |
using (var stream = new MemoryStream(Convert.FromBase64String(str))) | |
{ | |
try | |
{ | |
Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes"); | |
var a = (T)new BinaryFormatter().Deserialize(stream); | |
return a; | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine("TestStorage: " + e.Message); | |
return default(T); | |
} | |
} | |
} | |
public Dictionary<string, T> GetGroup<T>(string group) where T : new() | |
{ | |
var dictionary = new Dictionary<string, T>(); | |
if (storage.ContainsKey(group)) { | |
foreach (var kvp in storage[group]) { | |
var val = DeserializeObject<T>(kvp.Value); | |
dictionary.Add(kvp.Key, val); | |
} | |
} | |
return dictionary; | |
} | |
public Dictionary<string, string> GetGroup(string group) | |
{ | |
if (storage.ContainsKey(group)) { | |
return storage[group]; | |
} | |
return new Dictionary<string, string>(); | |
} | |
public IEnumerable<string> KeysForGroup(string group) | |
{ | |
if (storage.ContainsKey(group)) { | |
return storage[group].Keys; | |
} | |
return new List<string>(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment