diff --git a/ln.types.csproj b/ln.types.csproj index be117f3..1612429 100644 --- a/ln.types.csproj +++ b/ln.types.csproj @@ -126,6 +126,7 @@ + diff --git a/odb/ng/IdentityCache.cs b/odb/ng/IdentityCache.cs new file mode 100644 index 0000000..496b1ff --- /dev/null +++ b/odb/ng/IdentityCache.cs @@ -0,0 +1,56 @@ +using System; +using ln.types.collections; +namespace ln.types.odb.ng +{ + public class IdentityCache + { + WeakKeyReferenceDictionary reverseCache = new WeakKeyReferenceDictionary(); + WeakValueDictionary forwardCache = new WeakValueDictionary(); + + public IdentityCache() + { + } + + public bool TryGetValue(Guid identity,out object o) + { + lock (this) + { + return forwardCache.TryGetValue(identity, out o); + } + } + + public bool TryGetValue(Guid identity, out object o, Func instantiator) + { + lock (this) + { + if (!TryGetValue(identity, out o)) + { + o = instantiator(); + forwardCache.Add(identity, o); + reverseCache.Add(o, identity); + } + return false; + } + } + + public bool TryGetIdentity(object o,out Guid identity) + { + lock (this) + { + return reverseCache.TryGetValue(o, out identity); + } + } + + public void Ensure(Guid identity,object o) + { + lock (this) + { + if (!forwardCache.ContainsKey(identity)) + forwardCache.Add(identity, o); + if (!reverseCache.ContainsKey(o)) + reverseCache.Add(o, identity); + } + } + + } +} diff --git a/odb/ng/Mapper.cs b/odb/ng/Mapper.cs index 8f4ab43..7f08eb2 100644 --- a/odb/ng/Mapper.cs +++ b/odb/ng/Mapper.cs @@ -22,7 +22,8 @@ namespace ln.types.odb.ng public static Mapper Default { get; set; } = new Mapper((IStorageContainer)null); public IStorageContainer StorageContainer { get; private set; } - + public IdentityCache IdentityCache { get; } = new IdentityCache(); + Dictionary mappings = new Dictionary(); mappings.ObjectMapping ObjectMapping { get; } diff --git a/odb/ng/mappings/ClassMapping.cs b/odb/ng/mappings/ClassMapping.cs index 53c8f4f..d7f46d6 100644 --- a/odb/ng/mappings/ClassMapping.cs +++ b/odb/ng/mappings/ClassMapping.cs @@ -11,9 +11,6 @@ namespace ln.types.odb.ng.mappings public class ClassMapping : IODBMapping { - WeakKeyReferenceDictionary reverseCache = new WeakKeyReferenceDictionary(); - WeakValueDictionary forwardCache = new WeakValueDictionary(); - public delegate object GetID(object o); public delegate object SetID(object o, object id); @@ -51,26 +48,21 @@ namespace ln.types.odb.ng.mappings return false; } - private object GetObjectForDocument(Document document) + private object GetObjectForDocument(Mapper mapper,Document document) { - if (IsReferenceType && forwardCache.TryGetValue(document.ID, out object o)) - return o; - - object oi = Activator.CreateInstance(MappedType, true); - if (IsReferenceType) { - forwardCache.Add(document.ID, oi); - reverseCache.Add(oi, document.ID); + if (mapper.IdentityCache.TryGetValue(document.ID, out object o, () => Activator.CreateInstance(MappedType, true))) + return o; } - return oi; + return Activator.CreateInstance(MappedType, true); } public object UnmapValue(Mapper mapper,ODBEntity oval) { Document document = oval as Document; - object o = GetObjectForDocument(document); + object o = GetObjectForDocument(mapper,document); Apply(mapper, document, o); @@ -116,10 +108,7 @@ namespace ln.types.odb.ng.mappings if (IsReferenceType) { - if (!forwardCache.ContainsKey(documentID)) - forwardCache.Add(documentID, value); - if (!reverseCache.ContainsKey(value)) - reverseCache.Add(value, documentID); + mapper.IdentityCache.Ensure(documentID, value); } return document; @@ -130,10 +119,10 @@ namespace ln.types.odb.ng.mappings if (Object.ReferenceEquals(value, null)) return ODBNull.Instance; - if (!reverseCache.TryGetValue(value, out Guid documentID)) - documentID = Guid.NewGuid(); + if (!mapper.IdentityCache.TryGetIdentity(value, out Guid documentID)) + documentID = Guid.NewGuid(); - return MapDocument(mapper, documentID, value); + return MapDocument(mapper, documentID, value); } public Type GetFieldType(Mapper mapper,string fieldName)