// /** // * File: ODB.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using System.IO; using System.Collections.Generic; using Castle.DynamicProxy; using ln.types.serialize; using Castle.Components.DictionaryAdapter; using System.Linq; namespace ln.types.odb { public class ODB : ODB { public T Root { get => (T)RootObject; } public ODB(String basePath) :base(basePath, typeof(T)) { } } public class ODB { public object RootObject { get; protected set; } public String BasePath { get; set; } private ProxyGenerator proxyGenerator = new ProxyGenerator(); private Dictionary> persistentObjects = new Dictionary>(); private Dictionary persistentProxies = new Dictionary(); private Type RootType; public ODB(string basePath) { BasePath = Path.GetFullPath(basePath); if (!Directory.Exists(BasePath)) { Directory.CreateDirectory(BasePath); } } public ODB(String basePath, Type rootType) : this(basePath) { RootType = rootType; Initialize(); } public ODB(String basePath,object rootObject) : this(basePath) { RootType = rootObject.GetType(); RootObject = rootObject; Initialize(); } private void Initialize() { if (RootObject == null) { string rootHint = Path.Combine(BasePath, "root.hint"); if (File.Exists(rootHint)) { using (ObjectReader objectReader = new ObjectReader(rootHint)) { Guid persistenceID = objectReader.Read(); RootObject = GetPersistent(persistenceID); } } else { RootObject = Activator.CreateInstance(RootType); } } } IPersistent LoadPersistent(Guid guid) { IPersistent o = GetCachedPersistent(guid); if (o == null) { // ToDO: Implement Loading... throw new NotImplementedException(); } return o; } void SavePersistent(IPersistent o) => SavePersistent(o, true); void SavePersistent(IPersistent o,bool recurse) { MemoryStream objectStream = new MemoryStream(); ODBObjectWriter objectWriter = new ODBObjectWriter(this, objectStream); objectWriter.Write(o); byte[] persistentBytes = objectStream.ToArray(); IPersistent[] referencedObjects = objectWriter.ReferencedPersistents; if (recurse) { // Todo: Implement Recursive Object Save } } private IPersistent GetCachedPersistent(Guid persistenceID) { lock (this) { if (persistentObjects.ContainsKey(persistenceID)) { WeakReference weak = persistentObjects[persistenceID]; IPersistent persistent = null; if (weak.TryGetTarget(out persistent)) { return persistent; } else { persistentObjects.Remove(persistenceID); } } } return null; } /** * GetPersistent(..): Return Instance of an IPersistent (may be a proxy) * **/ public IPersistent GetPersistent(Guid persistenceID) { if (Guid.Empty.Equals(persistenceID)) return null; if (persistentObjects.ContainsKey(persistenceID)) { IPersistent o = GetCachedPersistent(persistenceID); if (o == null) { } return o; } return null; } public PT GetProxy(Guid persistentID) where PT : IPersistent { return default(PT); } public IPersistent GetProxy(Type type, Guid persistenceID) { LazyInterceptor lazyInterceptor = new LazyInterceptor(this, persistenceID); IPersistent persistent = proxyGenerator.CreateInterfaceProxyWithoutTarget(type, lazyInterceptor) as IPersistent; return persistent; } class ODBObjectWriter : ObjectWriter { public ODB ODB { get; } public IPersistent[] ReferencedPersistents => referencedPersistents.Values.ToArray(); private Dictionary referencedPersistents = new Dictionary(); public ODBObjectWriter(ODB odb,Stream stream) :base(stream) { ODB = odb; } public override object QueryReference(object o) { if (o is IPersistent) { IPersistent persistent = o as IPersistent; Guid persistenceID = persistent.GetPersistenceID(); if (!referencedPersistents.ContainsKey(persistenceID)) referencedPersistents.Add(persistenceID, persistent); return persistenceID; } return o; } } public class ODBObjectReader : ObjectReader { public ODB ODB { get; } public ODBObjectReader(ODB odb,Stream stream): base(stream) { ODB = odb; } public override object QueryReferencedObject(object re) { if (re is Guid) { Guid persistenceID = (Guid)re; IPersistent persistent = ODB.GetPersistent(persistenceID); return persistent; } return re; } } class LazyInterceptor : IInterceptor { ODB odb; WeakReference target = null; public LazyInterceptor(ODB odb, Guid persistentID) { this.odb = odb; } public void Intercept(IInvocation invocation) { object t = target; throw new NotImplementedException(); } } } }