ln.types/odb/ODB.cs
2019-03-20 13:28:56 +00:00

251 lines
6.9 KiB
C#

// /**
// * 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<T> : 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<Guid, WeakReference<IPersistent>> persistentObjects = new Dictionary<Guid, WeakReference<IPersistent>>();
private Dictionary<Guid, IPersistent> persistentProxies = new Dictionary<Guid, IPersistent>();
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<Guid>();
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<IPersistent> 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<PT>(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<Guid, IPersistent> referencedPersistents = new Dictionary<Guid, IPersistent>();
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<IPersistent> target = null;
public LazyInterceptor(ODB odb, Guid persistentID)
{
this.odb = odb;
}
public void Intercept(IInvocation invocation)
{
object t = target;
throw new NotImplementedException();
}
}
}
}