Skip to content

Instantly share code, notes, and snippets.

@mrozema
Last active October 21, 2018 12:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrozema/39d5a61fa0984168f69c7bb0190716ab to your computer and use it in GitHub Desktop.
Save mrozema/39d5a61fa0984168f69c7bb0190716ab to your computer and use it in GitHub Desktop.
PersistentStorage Xamarin implementation
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);
}
}
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>();
}
}
}
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