// /** // * 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 ReferencedPersistentIDs => referencedPersistentIDs; public IEnumerable ReferencedPersistents => referencedPersistents; List referencedPersistentIDs = new List(); HashSet referencedPersistents = new HashSet(); Dictionary fieldStore = new Dictionary(); 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 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; } } }