ln.types/odb/PreparedObject.cs

184 lines
5.8 KiB
C#

// /**
// * File: PreparedObject.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.Collections.Generic;
using System.CodeDom;
using System.Reflection;
using System.IO;
using System.Linq;
namespace ln.types.odb
{
public class PreparedObject
{
public ODB ODB { get; private set; }
public DateTime Timestamp { get; private set; }
public Type PreparedType { get; private set; }
public IPersistent Instance { get; set; }
public Guid PersistenceID { get; private set; }
public string[] StoredFieldNames => fieldStore.Keys.ToArray();
public IEnumerable<Guid> ReferencedPersistentIDs => referencedPersistentIDs;
public IEnumerable<IPersistent> ReferencedPersistents => referencedPersistents;
List<Guid> referencedPersistentIDs = new List<Guid>();
HashSet<IPersistent> referencedPersistents = new HashSet<IPersistent>();
Dictionary<string, byte[]> fieldStore = new Dictionary<string, byte[]>();
public PreparedObject(ODB odb,Type preparedType,Guid persistenceID)
{
ODB = odb;
Timestamp = DateTime.Now;
PreparedType = preparedType;
PersistenceID = persistenceID;
Instance = null;
}
public PreparedObject(ODB odb, IPersistent o)
{
ODB = odb;
Timestamp = DateTime.Now;
PreparedType = o.GetType();
PersistenceID = o.GetPersistenceID();
Instance = o;
SyncFromInstance();
}
private IEnumerable<FieldInfo> GetAllFields(Type type)
{
if (type == typeof(object))
{
return new FieldInfo[0];
}
else
{
return GetAllFields(type.BaseType).Concat(type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly));
}
}
private void SyncFromInstance()
{
referencedPersistentIDs.Clear();
FieldInfo[] fields = GetAllFields(PreparedType).ToArray();
foreach (FieldInfo fieldInfo in fields)
{
if (!fieldInfo.IsStatic)
{
object value = fieldInfo.GetValue(Instance);
if (value == null)
{
fieldStore[fieldInfo.Name] = new byte[0];
}
else
{
MemoryStream objectStream = new MemoryStream();
ODBObjectWriter objectWriter = new ODBObjectWriter(objectStream);
objectWriter.Write(value);
fieldStore[fieldInfo.Name] = objectStream.ToArray();
referencedPersistentIDs.AddRange(objectWriter.ReferencedPersistentIDs);
foreach (IPersistent persistent in objectWriter.ReferencedPersistents)
referencedPersistents.Add(persistent);
}
}
}
}
private void SyncToInstance()
{
foreach (FieldInfo fieldInfo in GetAllFields(PreparedType))
{
if (!fieldInfo.IsStatic)
{
byte[] bytes = fieldStore[fieldInfo.Name];
if (bytes.Length == 0)
{
fieldInfo.SetValue(Instance, null);
}
else
{
MemoryStream objectStream = new MemoryStream(fieldStore[fieldInfo.Name]);
ODBObjectReader objectReader = new ODBObjectReader(ODB, objectStream);
object value = objectReader.Read();
fieldInfo.SetValue(Instance, value);
}
}
}
}
public void ReConfigure(Type targetType,DateTime timestamp)
{
Timestamp = timestamp;
PreparedType = targetType;
fieldStore.Clear();
Instance = null;
}
public byte[] GetFieldBytes(string fieldName)
{
return fieldStore[fieldName];
}
public void SetFieldBytes(string fieldName,byte[] bytes)
{
fieldStore[fieldName] = bytes;
}
public IPersistent CreateInstance()
{
Instance = (IPersistent)Activator.CreateInstance(PreparedType,true);
SyncToInstance();
return Instance;
}
public bool InstanceEquals(PreparedObject other)
{
if (other == null)
return false;
if (Equals(other))
{
foreach (String fieldName in fieldStore.Keys)
{
byte[] me = fieldStore[fieldName];
byte[] you = other.fieldStore[fieldName];
File.WriteAllBytes("me.bin", me);
File.WriteAllBytes("you.bin", you);
if (!me.AreEqual(you))
return false;
}
return true;
}
return false;
}
public override int GetHashCode()
{
return PersistenceID.GetHashCode() ^ PreparedType.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is PreparedObject)
{
PreparedObject you = obj as PreparedObject;
return PreparedType.Equals(you.PreparedType) && PersistenceID.Equals(you.PersistenceID);
}
return false;
}
}
}