WIP
parent
c813829b51
commit
5f6674f07c
6
Cast.cs
6
Cast.cs
|
@ -25,14 +25,16 @@ namespace ln.types
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
object casted;
|
object casted;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!Implicit(value, targetType, out casted) &&
|
!Implicit(value, targetType, out casted) &&
|
||||||
!Implicit(value, value.GetType(), targetType, out casted) &&
|
!Implicit(value, value.GetType(), targetType, out casted) &&
|
||||||
!Explicit(value, targetType, out casted) &&
|
!Explicit(value, targetType, out casted) &&
|
||||||
!Explicit(value, value.GetType(), targetType, out casted)
|
!Explicit(value, value.GetType(), targetType, out casted)
|
||||||
)
|
)
|
||||||
throw new InvalidCastException();
|
{
|
||||||
|
casted = Convert.ChangeType(value, targetType);
|
||||||
|
}
|
||||||
return casted;
|
return casted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
namespace ln.types
|
||||||
|
{
|
||||||
|
class WeakHashValue<T> where T:class
|
||||||
|
{
|
||||||
|
readonly int keyHashCode;
|
||||||
|
|
||||||
|
WeakReference<T> reference;
|
||||||
|
|
||||||
|
public T Value => reference.TryGetTarget(out T target) ? target : null;
|
||||||
|
public bool IsStrong => reference.TryGetTarget(out T target);
|
||||||
|
|
||||||
|
public WeakHashValue(T value)
|
||||||
|
{
|
||||||
|
reference = new WeakReference<T>(value);
|
||||||
|
keyHashCode = value.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => keyHashCode;
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
T value = Value;
|
||||||
|
if ((value != null) && (obj is WeakHashValue<T>))
|
||||||
|
{
|
||||||
|
WeakHashValue<T> other = obj as WeakHashValue<T>;
|
||||||
|
return object.Equals(value,other.Value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,11 +30,15 @@ namespace ln.types.btree
|
||||||
|
|
||||||
public BTree()
|
public BTree()
|
||||||
{
|
{
|
||||||
if (!typeof(K).GetInterfaces().Contains(typeof(IComparable<K>)))
|
if (!typeof(K).GetInterfaces().Contains(typeof(IComparable<K>)))
|
||||||
throw new ArgumentException("BTree need to be constructed with Comparer<K> if T is not providing IComparable<K>");
|
{
|
||||||
|
Comparison = (K x, K y) => x.GetHashCode() - y.GetHashCode();
|
||||||
Comparison = (K x, K y) => ((IComparable<K>)x).CompareTo(y);
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
Comparison = (K x, K y) => ((IComparable<K>)x).CompareTo(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
public BTree(Comparison<K> comparison)
|
public BTree(Comparison<K> comparison)
|
||||||
{
|
{
|
||||||
Comparison = comparison;
|
Comparison = comparison;
|
||||||
|
@ -62,7 +66,7 @@ namespace ln.types.btree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Boolean TryGet(K key,ref V value)
|
public Boolean TryGet(K key,ref V value)
|
||||||
{
|
{
|
||||||
TreeNode node = Find(key);
|
TreeNode node = Find(key);
|
||||||
if (object.ReferenceEquals(node, null))
|
if (object.ReferenceEquals(node, null))
|
||||||
|
@ -112,7 +116,28 @@ namespace ln.types.btree
|
||||||
return Values.Contains(value);
|
return Values.Contains(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public K GetKey(K key)
|
||||||
|
{
|
||||||
|
if (TryGetKey(key, out K storedKey))
|
||||||
|
return storedKey;
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
public bool TryGetKey(K key,out K storedKey)
|
||||||
|
{
|
||||||
|
TreeNode treeNode = Find(key);
|
||||||
|
if (treeNode == null)
|
||||||
|
{
|
||||||
|
storedKey = default(K);
|
||||||
|
return false;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
storedKey = treeNode.Key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
{
|
{
|
||||||
headNode = null;
|
headNode = null;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
|
@ -107,7 +107,12 @@ namespace ln.types.btree
|
||||||
return _values.Count;
|
return _values.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<K> Keys => bTree.Keys;
|
public void Clear()
|
||||||
|
{
|
||||||
|
bTree.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<K> Keys => bTree.Keys;
|
||||||
public IEnumerable<V> Values => bTree.Values.SelectMany(vl => vl);
|
public IEnumerable<V> Values => bTree.Values.SelectMany(vl => vl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,217 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ln.types.btree;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace ln.types.collections
|
||||||
|
{
|
||||||
|
public class WeakKeyDictionary<K, V> : IDictionary<K, V> where K : class
|
||||||
|
{
|
||||||
|
BTreeValueList<int, WeakKeyValuePair<K, V>> store = new BTreeValueList<int, WeakKeyValuePair<K, V>>();
|
||||||
|
|
||||||
|
public WeakKeyDictionary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public V this[K key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (TryGetValue(key, out V value))
|
||||||
|
return value;
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(key, value, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WeakKeyValuePair<K, V> FindKeyValuePair(K key)
|
||||||
|
{
|
||||||
|
int keyHashCode = key.GetHashCode();
|
||||||
|
if (store.ContainsKey(keyHashCode))
|
||||||
|
foreach (WeakKeyValuePair<K, V> weakKeyValuePair in store[keyHashCode])
|
||||||
|
{
|
||||||
|
K weakKey = weakKeyValuePair.Key;
|
||||||
|
if (weakKey == null)
|
||||||
|
{
|
||||||
|
store.Remove(keyHashCode, weakKeyValuePair);
|
||||||
|
}
|
||||||
|
else if (Object.Equals(key, weakKey))
|
||||||
|
{
|
||||||
|
return weakKeyValuePair;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(K key, out V value)
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<K, V> weakKeyValuePair = FindKeyValuePair(key);
|
||||||
|
if (weakKeyValuePair != null)
|
||||||
|
{
|
||||||
|
value = weakKeyValuePair.Value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
value = default(V);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue(K key, V value) => SetValue(key, value, false);
|
||||||
|
public bool SetValue(K key, V value, bool replace)
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<K, V> weakKeyValuePair = FindKeyValuePair(key);
|
||||||
|
if (weakKeyValuePair == null)
|
||||||
|
{
|
||||||
|
weakKeyValuePair = new WeakKeyValuePair<K, V>(key, value);
|
||||||
|
store.Add(key.GetHashCode(), weakKeyValuePair);
|
||||||
|
return false;
|
||||||
|
} else if (replace)
|
||||||
|
{
|
||||||
|
weakKeyValuePair.Value = value;
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Key already present");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<K> Keys
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<K> keys = new List<K>();
|
||||||
|
|
||||||
|
foreach (WeakKeyValuePair<K,V> weakKeyValuePair in store.Values)
|
||||||
|
{
|
||||||
|
if (weakKeyValuePair.IsStrong)
|
||||||
|
keys.Add(weakKeyValuePair.Key);
|
||||||
|
else
|
||||||
|
store.Remove(weakKeyValuePair.keyHashCode, weakKeyValuePair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<V> Values
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<V> values = new List<V>();
|
||||||
|
|
||||||
|
foreach (WeakKeyValuePair<K, V> weakKeyValuePair in store.Values)
|
||||||
|
{
|
||||||
|
if (weakKeyValuePair.IsStrong)
|
||||||
|
values.Add(weakKeyValuePair.Value);
|
||||||
|
else
|
||||||
|
store.Remove(weakKeyValuePair.keyHashCode, weakKeyValuePair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count => store.Keys.Count();
|
||||||
|
public bool IsReadOnly => false;
|
||||||
|
|
||||||
|
public void Add(K key, V value)
|
||||||
|
{
|
||||||
|
SetValue(key, value);
|
||||||
|
}
|
||||||
|
public void Add(KeyValuePair<K, V> item) => Add(item.Key, item.Value);
|
||||||
|
|
||||||
|
public void Clear() => store.Clear();
|
||||||
|
public bool Contains(KeyValuePair<K, V> item)
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<K, V> weakKeyValuePair = FindKeyValuePair(item.Key);
|
||||||
|
if ((weakKeyValuePair != null) && weakKeyValuePair.IsStrong)
|
||||||
|
{
|
||||||
|
return Object.Equals(item.Value, weakKeyValuePair.Value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public bool ContainsKey(K key)
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<K, V> weakKeyValuePair = FindKeyValuePair(key);
|
||||||
|
return (weakKeyValuePair != null) && weakKeyValuePair.IsStrong;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
foreach (WeakKeyValuePair<K, V> weakKeyValuePair in store.Values)
|
||||||
|
{
|
||||||
|
if (weakKeyValuePair.IsStrong)
|
||||||
|
array[arrayIndex++] = new KeyValuePair<K, V>(weakKeyValuePair.Key,weakKeyValuePair.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
|
||||||
|
{
|
||||||
|
foreach (WeakKeyValuePair<K,V> weakKeyValuePair in store.Values)
|
||||||
|
{
|
||||||
|
if (weakKeyValuePair.IsStrong)
|
||||||
|
yield return new KeyValuePair<K, V>(weakKeyValuePair.Key,weakKeyValuePair.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(K key)
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<K, V> weakKeyValuePair = FindKeyValuePair(key);
|
||||||
|
if (weakKeyValuePair != null)
|
||||||
|
{
|
||||||
|
store.Remove(weakKeyValuePair.keyHashCode, weakKeyValuePair);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(KeyValuePair<K, V> item)
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<K, V> weakKeyValuePair = FindKeyValuePair(item.Key);
|
||||||
|
if ((weakKeyValuePair != null) && (object.Equals(item.Value, weakKeyValuePair.Value)))
|
||||||
|
{
|
||||||
|
store.Remove(weakKeyValuePair.keyHashCode, weakKeyValuePair);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|
||||||
|
class WeakKeyValuePair<TK,TV> where TK: class
|
||||||
|
{
|
||||||
|
public readonly int keyHashCode;
|
||||||
|
|
||||||
|
WeakReference<TK> reference;
|
||||||
|
|
||||||
|
public TK Key => reference.TryGetTarget(out TK target) ? target : null;
|
||||||
|
public bool IsStrong => reference.TryGetTarget(out TK target);
|
||||||
|
|
||||||
|
public V Value { get; set; }
|
||||||
|
|
||||||
|
public WeakKeyValuePair(TK key,V value)
|
||||||
|
{
|
||||||
|
reference = new WeakReference<TK>(key);
|
||||||
|
keyHashCode = value.GetHashCode();
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => keyHashCode;
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
TK key = Key;
|
||||||
|
if ((key != null) && (obj is WeakKeyValuePair<TK,TV>))
|
||||||
|
{
|
||||||
|
WeakKeyValuePair<TK, TV> other = obj as WeakKeyValuePair<TK, TV>;
|
||||||
|
return object.Equals(key, other.Value);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,6 +119,9 @@
|
||||||
<Compile Include="odb\ng\diff\Diff.cs" />
|
<Compile Include="odb\ng\diff\Diff.cs" />
|
||||||
<Compile Include="odb\ng\diff\DocumentDiff.cs" />
|
<Compile Include="odb\ng\diff\DocumentDiff.cs" />
|
||||||
<Compile Include="odb\ng\diff\ListDiff.cs" />
|
<Compile Include="odb\ng\diff\ListDiff.cs" />
|
||||||
|
<Compile Include="collections\WeakKeyDictionary.cs" />
|
||||||
|
<Compile Include="test\WeakKeyDictionaryTests.cs" />
|
||||||
|
<Compile Include="WeakHashValue.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="odb\" />
|
<Folder Include="odb\" />
|
||||||
|
|
|
@ -166,7 +166,7 @@ namespace ln.types.odb.ng
|
||||||
|
|
||||||
static Document()
|
static Document()
|
||||||
{
|
{
|
||||||
RegisterDeserializer(0x1001, (b,o,l) => new Document(b,o+16,l));
|
RegisterDeserializer(0x1001, (b,o,l) => new Document(b,o,l));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace ln.types.odb.ng
|
||||||
if (object.ReferenceEquals(value,null))
|
if (object.ReferenceEquals(value,null))
|
||||||
value = ODBNull.Instance;
|
value = ODBNull.Instance;
|
||||||
|
|
||||||
return IF(propertyName, (v) => value.Equals(v));
|
return IF(propertyName, (v) => value.CompareTo(v)==0);
|
||||||
}
|
}
|
||||||
public static Query EqualsNot<T>(string propertyName, ODBEntity value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
|
public static Query EqualsNot<T>(string propertyName, ODBEntity value) => EqualsNot(IndexPath.TranslatePropertyPath(typeof(T), propertyName), value);
|
||||||
public static Query EqualsNot(String propertyName, ODBEntity value)
|
public static Query EqualsNot(String propertyName, ODBEntity value)
|
||||||
|
@ -49,13 +49,18 @@ namespace ln.types.odb.ng
|
||||||
if (object.ReferenceEquals(value, null))
|
if (object.ReferenceEquals(value, null))
|
||||||
value = ODBNull.Instance;
|
value = ODBNull.Instance;
|
||||||
|
|
||||||
return IF(propertyName, (v) => !value.Equals(v));
|
return IF(propertyName, (v) => value.CompareTo(v)!=0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Query Equals<T>(string propertyName, ODBEntity[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
|
public static Query Equals<T>(string propertyName, ODBEntity[] values) => Equals(IndexPath.TranslatePropertyPath(typeof(T), propertyName), values);
|
||||||
public static Query Equals(String propertyName, ODBEntity[] values)
|
public static Query Equals(String propertyName, ODBEntity[] values)
|
||||||
{
|
{
|
||||||
return IF(propertyName, (v) => values.Contains(v));
|
return IF(propertyName, (v) => {
|
||||||
|
foreach (ODBEntity value in values)
|
||||||
|
if (value.CompareTo(v) == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Query Contains<T, A>(string propertyName, IEnumerable<A> values)
|
public static Query Contains<T, A>(string propertyName, IEnumerable<A> values)
|
||||||
|
|
|
@ -4,20 +4,21 @@ using System.Reflection;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using ln.logging;
|
using ln.logging;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using ln.types.collections;
|
||||||
|
|
||||||
namespace ln.types.odb.ng.mappings
|
namespace ln.types.odb.ng.mappings
|
||||||
{
|
{
|
||||||
|
|
||||||
public class ClassMapping : IODBMapping
|
public class ClassMapping : IODBMapping
|
||||||
{
|
{
|
||||||
|
WeakKeyDictionary<object, Guid> cache = new WeakKeyDictionary<object, Guid>();
|
||||||
|
|
||||||
|
|
||||||
public delegate object GetID(object o);
|
public delegate object GetID(object o);
|
||||||
public delegate object SetID(object o, object id);
|
public delegate object SetID(object o, object id);
|
||||||
|
|
||||||
public Type MappedType { get; }
|
public Type MappedType { get; }
|
||||||
|
|
||||||
//public GetID getID { get; private set; } = (o) => Guid.NewGuid();
|
|
||||||
//public Type IDType { get; private set; }
|
|
||||||
|
|
||||||
List<FieldInfo> mappedFields = new List<FieldInfo>();
|
List<FieldInfo> mappedFields = new List<FieldInfo>();
|
||||||
|
|
||||||
public ClassMapping(Type type)
|
public ClassMapping(Type type)
|
||||||
|
@ -139,8 +140,11 @@ namespace ln.types.odb.ng.mappings
|
||||||
{
|
{
|
||||||
if (Object.ReferenceEquals(value, null))
|
if (Object.ReferenceEquals(value, null))
|
||||||
return ODBNull.Instance;
|
return ODBNull.Instance;
|
||||||
|
|
||||||
return MapDocument(mapper, Guid.Empty, value);
|
if (!cache.TryGetValue(value, out Guid documentID))
|
||||||
|
documentID = Guid.NewGuid();
|
||||||
|
|
||||||
|
return MapDocument(mapper, documentID, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type GetFieldType(Mapper mapper,string fieldName)
|
public Type GetFieldType(Mapper mapper,string fieldName)
|
||||||
|
|
|
@ -7,7 +7,7 @@ using ln.types.threads;
|
||||||
using ln.types.odb.ng.diff;
|
using ln.types.odb.ng.diff;
|
||||||
namespace ln.types.odb.ng.storage.session
|
namespace ln.types.odb.ng.storage.session
|
||||||
{
|
{
|
||||||
class SessionStorage : ChainedStorage
|
public class SessionStorage : ChainedStorage
|
||||||
{
|
{
|
||||||
public SessionStorageContainer SessionContainer { get; }
|
public SessionStorageContainer SessionContainer { get; }
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace ln.types.odb.values
|
||||||
public override byte[] GetStorageBytes() => BitConverter.GetBytes((uint)Value);
|
public override byte[] GetStorageBytes() => BitConverter.GetBytes((uint)Value);
|
||||||
protected override int compare(ODBEntity other)
|
protected override int compare(ODBEntity other)
|
||||||
{
|
{
|
||||||
long d = (long)Value - (long)(other as ODBValue).Value;
|
long d = Convert.ToInt64((uint)Value) - Convert.ToInt64((uint)(other as ODBValue).Value);
|
||||||
if (d == 0)
|
if (d == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (d < 0)
|
if (d < 0)
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
using NUnit.Framework;
|
using System;
|
||||||
using System;
|
|
||||||
using ln.types.odb.ng;
|
|
||||||
using ln.types.odb.ng.storage;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using ln.types.odb.values;
|
using ln.types.odb.ng;
|
||||||
|
using ln.types.odb.ng.storage;
|
||||||
using ln.types.odb.ng.storage.fs;
|
using ln.types.odb.ng.storage.fs;
|
||||||
using ln.types.odb.ng.storage.session;
|
using ln.types.odb.ng.storage.session;
|
||||||
|
using ln.types.odb.values;
|
||||||
|
using NUnit.Framework;
|
||||||
namespace ln.types.test
|
namespace ln.types.test
|
||||||
{
|
{
|
||||||
[TestFixture()]
|
[TestFixture()]
|
||||||
public class ODBTests
|
public class ODBTests
|
||||||
{
|
{
|
||||||
[SetUp()]
|
[SetUp()]
|
||||||
|
@ -48,6 +48,9 @@ namespace ln.types.test
|
||||||
|
|
||||||
document[new ODBStringValue("FeldA")] = new ODBStringValue("FeldA");
|
document[new ODBStringValue("FeldA")] = new ODBStringValue("FeldA");
|
||||||
document[new ODBStringValue("FeldB")] = new ODBStringValue("FeldB");
|
document[new ODBStringValue("FeldB")] = new ODBStringValue("FeldB");
|
||||||
|
Document nestedDocument = new Document();
|
||||||
|
nestedDocument["EineZeichenkette"] = new ODBStringValue("Ich bin eine Zeichenkette");
|
||||||
|
document[new ODBStringValue("FeldDokument")] = nestedDocument;
|
||||||
|
|
||||||
storage.Save(document);
|
storage.Save(document);
|
||||||
|
|
||||||
|
@ -110,6 +113,9 @@ namespace ln.types.test
|
||||||
Assert.AreEqual(1, mapper.Load<Person>(Query.Equals<Person>("FirstName", "Harald")).Count());
|
Assert.AreEqual(1, mapper.Load<Person>(Query.Equals<Person>("FirstName", "Harald")).Count());
|
||||||
Assert.AreEqual(1, mapper.Load<Person>(Query.Equals<Person>("FirstName", "Liesschen")).Count());
|
Assert.AreEqual(1, mapper.Load<Person>(Query.Equals<Person>("FirstName", "Liesschen")).Count());
|
||||||
|
|
||||||
|
Person harald = mapper.Load<Person>(Query.Equals<Person>("FirstName", "Harald")).FirstOrDefault();
|
||||||
|
|
||||||
|
Assert.AreEqual(persons[0], harald);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -161,12 +167,24 @@ namespace ln.types.test
|
||||||
|
|
||||||
public class Person
|
public class Person
|
||||||
{
|
{
|
||||||
|
public readonly Guid ID;
|
||||||
|
|
||||||
public String FirstName = "";
|
public String FirstName = "";
|
||||||
public String[] MiddleNames = new string[0];
|
public String[] MiddleNames = new string[0];
|
||||||
public String LastName = "";
|
public String LastName = "";
|
||||||
|
|
||||||
public int Age = 18;
|
public int Age = 18;
|
||||||
}
|
|
||||||
|
public Person()
|
||||||
|
{
|
||||||
|
ID = Guid.NewGuid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => ID.GetHashCode();
|
||||||
|
public override bool Equals(object obj) => (obj is Person) && ID.Equals((obj as Person).ID);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using ln.types.collections;
|
||||||
|
using System.Threading;
|
||||||
|
namespace ln.types.test
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class WeakKeyDictionaryTests
|
||||||
|
{
|
||||||
|
class KeyClass
|
||||||
|
{
|
||||||
|
static int next = 1;
|
||||||
|
|
||||||
|
public readonly int Value = next++;
|
||||||
|
|
||||||
|
public override int GetHashCode() => Value;
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return ((obj is KeyClass) && ((obj as KeyClass).Value == Value));
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return string.Format("[KeyClass Value={0}]",Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyClass[] keys = new KeyClass[1024];
|
||||||
|
WeakKeyDictionary<KeyClass, int> testDict = new WeakKeyDictionary<KeyClass, int>();
|
||||||
|
|
||||||
|
public void Fill()
|
||||||
|
{
|
||||||
|
for (int n = 0; n < keys.Length; n++)
|
||||||
|
{
|
||||||
|
keys[n] = new KeyClass();
|
||||||
|
testDict.Add(keys[n], n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Strip()
|
||||||
|
{
|
||||||
|
keys[0] = null;
|
||||||
|
keys[keys.Length - 1] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase()]
|
||||||
|
public void TestWeakKeyDictionary()
|
||||||
|
{
|
||||||
|
Fill();
|
||||||
|
|
||||||
|
Thread.Sleep(250);
|
||||||
|
|
||||||
|
Assert.AreEqual(keys.Length, testDict.Count);
|
||||||
|
Assert.AreEqual(keys.Length, testDict.Keys.Count);
|
||||||
|
|
||||||
|
Strip();
|
||||||
|
|
||||||
|
Thread.Sleep(250);
|
||||||
|
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
Thread.Sleep(250);
|
||||||
|
|
||||||
|
Assert.AreEqual(keys.Length-2, testDict.Keys.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue