/// <summary> /// Calculates the surrogates to be persisted or removes the ones that do not have valid references /// </summary> public void CalculateSurrogatesToBePersisted() { var currentSurrogates = new StateObjectSurrogate[_surrogates.Values.Count]; _surrogates.Values.CopyTo(currentSurrogates, 0); bool removedSurrogate; //Step 1. Make sure that the surrogates have valid references, otherwise are removed. do { removedSurrogate = false; for (int i = currentSurrogates.Length - 1; i >= 0; i--) { var surrogate = currentSurrogates[i]; if (surrogate == null) { continue; } lock (surrogate) { if (!surrogate.ShouldBeSerialized()) { currentSurrogates[i] = null; removedSurrogate = true; //The surrogate won't persist and will be removed from the storage if present. _stateManager.RemoveObject(surrogate.UniqueID, false, true); } } } } while (removedSurrogate); //Step 2. Was there are removed surrogate? then make sure the remaining where not dependent of them. //No removed surrogates then this is the final list. _surrogatesToBePersisted = currentSurrogates; }
internal IStateObject GetSurrogateFirstReference(StateObjectSurrogate obj) { lock (obj) { return(_stateManager.GetObject(obj.objectRefs[0].UniqueID)); } }
internal void AddSurrogateReference(StateObjectSurrogate surrogate, IStateObject reference) { lock (surrogate) { surrogate.AddReference(new LazyStateObjectReference(_stateManager, reference)); } }
/// <summary> /// Sometimes while serializing a "DisplayClass" we might find fields that reference /// IStateObjects. /// Promises are persisted using the Surrogates mechanism, and we also are aware that /// Surrogates are the last thing to be serialized. /// Processes like adoption occur even before StateManager.Persist is started. /// When the value for these fields are serialized, it might happen that there are still "unattached" /// so they need to be adopted /// </summary> /// <param name="instance"></param> /// <param name="value"></param> internal StateObjectSurrogate GetOrphanHolder(object instance, IStateObject value, string fieldName) { if (!StateManager.AllBranchesAttached(value.UniqueID)) { var displayClassSurrogate = _stateManager.surrogateManager.GetSurrogateFor(instance, generateIfNotFound: false); if (displayClassSurrogate == null) { throw new InvalidOperationException("A surrogate is needed"); } //Retrieve surrogate StateObjectSurrogate surrogate = (StateObjectSurrogate)_stateManager.surrogateManager.GetSurrogateFor(value, generateIfNotFound: true); if (surrogate == null) { throw new Exception("Object must be instantiated/registered with resolve"); } //Add reference if needed _stateManager.surrogateManager.AddSurrogateReference(surrogate, displayClassSurrogate.UniqueID); AddSurrogateHolder(surrogate); return(surrogate); } else { return(null); } }
public void RemoveSurrogateReference(StateObjectSurrogate surrogate, IStateObject oldReference) { if (oldReference != null && surrogate != null) { RemoveSurrogateReference(surrogate, oldReference.UniqueID); } }
internal void AddSurrogateReference(StateObjectSurrogate surrogate, string uniqueId) { lock (surrogate) { surrogate.AddReference(new LazyStateObjectReference(_stateManager, uniqueId)); } }
/// <summary> /// Retrieves or creates a surrogate object for a value /// </summary> /// <param name="newValueObject"></param> /// <param name="generateIfNotFound"></param> /// <returns></returns> private StateObjectSurrogate GetSurrogateForBeforePersist(object newValueObject, bool generateIfNotFound, string parentSurrogate = null) { #if DEBUG Debug.Assert(newValueObject != null, "Surrogates cannot be registered for null values"); #endif StateObjectSurrogate surrogate; lock (this) { if (_surrogates.TryGetValue(newValueObject, out surrogate)) { return(surrogate); } if (generateIfNotFound) { #if DEBUG if (AllDependenciesAreProcessed) { Debug.WriteLine("Invalid surrogate reference. This might be caused by a calculated property that is being call to get an object JSON. Please analyze the callstack and make the proper code changes.\r\nCall Stack: \r\n: {0}", new StackTrace(true).ToString()); } #endif surrogateDirectoryLock.EnterUpgradeableReadLock(); try { surrogateDirectoryLock.EnterWriteLock(); try { var parentSurrogateUniqueID = (parentSurrogate == null ? "" : UniqueIDGenerator.UniqueIdSeparator + parentSurrogate); _surrogates.Add(newValueObject, surrogate = new StateObjectSurrogate { UniqueID = "!" + _stateManager.UniqueIDGenerator.GetUniqueID() + parentSurrogateUniqueID, Value = newValueObject }); //REMOVE _stateManager.AddNewObject(surrogate); //TODO Add in stateManager not mark as dirty because all surrogates are dirty //We need to add the uniqueID to the surrogatesIdsToSurrogates //because this table is used to match surrogates instances to their //corresponding uniqueid because obviously surrogates do not have the uniqueId property _surrogatesIdsToSurrogates.Add(surrogate.UniqueID, surrogate); } finally { surrogateDirectoryLock.ExitWriteLock(); } } finally { surrogateDirectoryLock.ExitUpgradeableReadLock(); } //Trace.TraceInformation("A new surrogate ID {0} for object of type {1} has been created", surrogate.UniqueID, newValueObject.GetType()); } } return(surrogate); }
public void RemoveSurrogateReference(StateObjectSurrogate surrogate, string uniqueIdOfLastReferent) { lock (surrogate) { surrogate.RemoveReference(uniqueIdOfLastReferent); if (surrogate.objectRefs.Count == 0) { _stateManager.RemoveObject(surrogate.UniqueID, true); } } }
private void GetResolvedValueEx(DependencyResolutionInfo dependency) { var surrogateManager = _stateManager.surrogateManager; var value = dependency.value; var istateObjectValue = dependency.value as IStateObject; if (istateObjectValue != null) { //The value is an state object if (_stateManager.IsInElementsToRemove(istateObjectValue.UniqueID)) { //If the object is present in the elements it is detached from so its UniqueID //is changed to a temporal one. //The current in the session must be removed _stateManager.DettachObject(istateObjectValue); } dependency.canBeAnOrphan = !StateManager.AllBranchesAttached(istateObjectValue); dependency.ResolvedValue = istateObjectValue; dependency.IsStateObject = true; } else if (value is ISurrogateEventsInfo) { dependency.ResolvedValue = value; dependency.isEventsInfo = true; } else { //if (surrogateManager.IsSurrogateRegistered(value.GetType())) Commented for performance StateObjectSurrogate currentSurrogate = null; //Get the surrogate instance from the surrogates that are already loaded in memory or create one dependency.ResolvedValue = currentSurrogate = dependency.ResolvedSurrogate = surrogateManager.GetSurrogateFor(value, generateIfNotFound: true); if (currentSurrogate == null) { throw new ArgumentException("A surrogate could not be gotten for value of type " + value.GetType().FullName); } if (_stateManager.IsInElementsToRemove(currentSurrogate.UniqueID)) { //If the object is present in the elements it is restored, //since it is a top element no adoption needs to be performed _stateManager.UndoRemove(currentSurrogate.UniqueID); //We must unremove the Value surrogate var valueUniqueID = UniqueIDGenerator.GetRelativeUniqueID(currentSurrogate, StateObjectSurrogate.VALUE_PREFIX); _stateManager.UndoRemove(valueUniqueID); } else { //OK } } }
public void SaveSurrogate(StateObjectSurrogate surrogate) { //Save surrogate header var surrogateContext = StateManager.Current.surrogateManager.GetSurrogateContext(surrogate.UniqueID, surrogate); var raw = SurrogatesDirectory.ObjectToRaw(surrogate, surrogateContext); SaveRaw(surrogate.UniqueID, raw); //Save surrogate value var uid = UniqueIDGenerator.GetRelativeUniqueID(surrogate, StateObjectSurrogate.VALUE_PREFIX); surrogateContext = StateManager.Current.surrogateManager.GetSurrogateContext(uid, surrogate.Value); raw = SurrogatesDirectory.ObjectToRaw(surrogate.Value, surrogateContext); SaveRaw(uid, raw); }
public void SaveSurrogate(StateObjectSurrogate surrogate) { //Saving surrogate header var surrogatecontext = _surrogateManager.GetSurrogateContext(surrogate.UniqueID, surrogate); var raw = SurrogatesDirectory.ObjectToRaw(surrogate, surrogatecontext); SaveRaw(surrogate.UniqueID, raw); //Saving surrogateValue if (surrogate.ShouldSerializeValue) { var uid = UniqueIDGenerator.GetRelativeUniqueID(surrogate, StateObjectSurrogate.VALUE_PREFIX); surrogatecontext = _surrogateManager.GetSurrogateContext(uid, surrogate.Value); raw = SurrogatesDirectory.ObjectToRaw(surrogate.Value, surrogatecontext); SaveRaw(uid, raw); } }
/// <summary> /// Registers which pointers are using this surrogate. /// This is important because a surrogate with no references should be deleted /// </summary> /// <param name="surrogate"></param> /// <param name="pointer"></param> /// <param name="isNewPointer"></param> internal void AddSurrogateReference(StateObjectSurrogate surrogate, StateObjectPointer pointer, bool isNewPointer = true) { //Check if reference already exits lock (surrogate) { surrogate.AddReference(new LazyStateObjectReference(_stateManager, pointer)); } //RegisterSurrogatedObject(surrogate, pointer.UniqueID); pointer.Target = surrogate; if (isNewPointer) { _stateManager.AddNewObject(pointer); } else if (StateManager.AllBranchesAttached(pointer)) { _stateManager.StorageManager.SaveObject(pointer); } _stateManager.UndoRemove(pointer.UniqueID); }
private object GetResolvedValue(object value) { if (value == null) { return(value); } if (_stateManager.surrogateManager.IsSurrogateRegistered(value.GetType())) { StateObjectSurrogate currentSurrogate = null; if (_stateManager.surrogateManager.GetSurrogates().TryGetValue(value, out currentSurrogate)) { return(currentSurrogate); } else { return(null); } } else { return(value); } }
private StateObjectSurrogate GetSurrogateForAfterPersist(object newValueObject, bool generateIfNotFound, string parentSurrogate = null) { StateObjectSurrogate surrogate; lock (this) { if (_surrogates.TryGetValue(newValueObject, out surrogate)) { //The surrogate could exist but it was not worthy of serialization //In old times, surrogates were in charge of serialization and reference management //Now these dependencies are handle in the SurrogateDependencyManager. //So we now asumme we should not validate if the surrogate is worthy or not. return(surrogate); } if (generateIfNotFound) { #if DEBUG if (AllDependenciesAreProcessed) { Debug.WriteLine("Invalid surrogate reference. This might be caused by a calculated property that is being call to get an object JSON. Please analyze the callstack and make the proper code changes.\r\nCall Stack: \r\n: {0}", new StackTrace(true).ToString()); } #endif //was it that it is present but was not worthy? if (surrogate != null) { if (lastMinuteSurrogates == null || !lastMinuteSurrogates.Contains(surrogate)) { //We need to update the UniqueID if (parentSurrogate != null) { surrogate.UniqueID = "!" + _stateManager.UniqueIDGenerator.GetUniqueID() + UniqueIDGenerator.UniqueIdSeparator + parentSurrogate; if (surrogate.UniqueID.StartsWith("!r")) { Trace.WriteLine("Surrogate = " + surrogate.UniqueID); Trace.WriteLine(new StackTrace(true).ToString()); } _surrogates[surrogate.Value] = surrogate; _surrogatesIdsToSurrogates[surrogate.UniqueID] = surrogate; } } } else { var parentSurrogateUniqueID = (parentSurrogate == null ? "" : UniqueIDGenerator.UniqueIdSeparator + parentSurrogate); _surrogates.Add(newValueObject, surrogate = new StateObjectSurrogate { UniqueID = "!" + _stateManager.UniqueIDGenerator.GetUniqueID() + parentSurrogateUniqueID, Value = newValueObject }); _surrogatesIdsToSurrogates.Add(surrogate.UniqueID, surrogate); } //Add to last minute surrogate lastMinuteSurrogates = lastMinuteSurrogates ?? new HashSet <StateObjectSurrogate>(ComparerByReference.CommonInstance); if (parentSurrogate != null) { _stateManager.surrogateManager.AddSurrogateReference(surrogate, parentSurrogate); } lastMinuteSurrogates.Add(surrogate); } } return(surrogate); }
public void SendToSurrogatesToBePersisted(StateObjectSurrogate surrogate) { _surrogatesToBePersisted[surrogate.UniqueID] = surrogate; }
public void AddSurrogateHolder(StateObjectSurrogate value) { throw new NotImplementedException(); }
private void AddSurrogateHolder(StateObjectSurrogate value) { _orphanHolders.Add(value); }
internal static void DeserializeStateForDelegate(BinaryReader reader, Type delegateClassType, object instance, ref string fieldName, string prefix = null) { var formatter = new BinaryFormatter(); var fieldList = delegateClassType.Fields(BindingFlags.Public | BindingFlags.Instance); foreach (var field in fieldList) { if (fieldName == null) { if (reader.BaseStream.Position == reader.BaseStream.Length) {/*No more data*/ return; } fieldName = reader.ReadString(); if (prefix != null) { if (fieldName.StartsWith(prefix, StringComparison.Ordinal)) { fieldName = fieldName.Substring(prefix.Length); } } TraceUtil.WriteLine(string.Format("Setting value for field {0}", fieldName)); } //Skip until find matching field if (!fieldName.Equals(field.Name, StringComparison.Ordinal)) { continue; } if (field.Name.Contains("<>") && field.Name.Contains("locals")) { //Is it in locals?? //Check if still goes here. var surrogateUID = reader.ReadString(); var localsSurrogate = (StateObjectSurrogate)StateManager.Current.GetObject(surrogateUID); var localsInstance = localsSurrogate.Value; field.SetValue(instance, localsInstance); fieldName = null; continue; } //Is not locals.mmm ok is it an StateObject if (typeof(IStateObject).IsAssignableFrom(field.FieldType) || (field.FieldType.IsGenericType && (typeof(IList <>).IsAssignableFrom(field.FieldType.GetGenericTypeDefinition()) || typeof(IDictionary <,>).IsAssignableFrom(field.FieldType.GetGenericTypeDefinition())) )) { var uid = reader.ReadString(); if (!String.IsNullOrWhiteSpace(uid)) { var fieldValue = StateManager.Current.GetObject(uid); var surrogate = fieldValue as StateObjectSurrogate; if (surrogate != null) { fieldValue = surrogate.Value as IStateObject; } field.SetValue(instance, fieldValue); } fieldName = null; } else if (typeof(ILogicWithViewModel <IStateObject>).IsAssignableFrom(field.FieldType)) { fieldName = null; var uid = reader.ReadString(); var vm = StateManager.Current.GetObject(uid); if (vm != null) { Type logicType = field.FieldType; if (logicType.IsInterface) { var logicAttr = vm.GetType().GetCustomAttribute(typeof(UpgradeHelpers.Helpers.LogicAttribute)) as UpgradeHelpers.Helpers.LogicAttribute; if (logicAttr == null) { throw new InvalidOperationException("The logic type for the viewmodel could not be determined. Please decorate the ViewModel class type with the Logic Attribute. for example [Logic(Type = typeof(LogicClass)]"); } logicType = logicAttr.Type; } var form = IocContainerImplWithUnity.Current.Resolve(logicType, null, IIocContainerFlags.NoView | IIocContainerFlags.RecoveredFromStorage) as ILogicView <IViewModel>; form.SetPropertyValue("ViewModel", vm); field.SetValue(instance, form); } else { throw new InvalidOperationException(string.Format("The ViewModel for field {0} could not be restored ", field.Name)); } } else { if (field.FieldType.IsSerializable && typeof(MulticastDelegate).IsAssignableFrom(field.FieldType)) { RestoreDelegateField(reader, instance, field); } else if (SurrogatesDirectory.IsSurrogateRegistered(field.FieldType)) { var uid = reader.ReadString(); if (!String.IsNullOrWhiteSpace(uid)) { StateObjectSurrogate surrogate = StateManager.Current.surrogateManager.GetObject(uid); field.SetValue(instance, surrogate.Value); } } else if (field.FieldType.IsSerializable) { var fieldValue = formatter.Deserialize(reader.BaseStream); field.SetValue(instance, fieldValue); } fieldName = null; } } }
/// <summary> /// Tries to recover an StateObject instance thru an StateObjectPointer /// </summary> /// <param name="input"></param> /// <param name="propEx"></param> /// <param name="parentInstance"></param> /// <param name="forSurrogate"></param> /// <param name="updateProperty"></param> /// <returns></returns> internal static object TryToRecoverWithPointer(StateManager stateManager, PropertyInfoEx propEx, IStateObject parentInstance, bool forSurrogate, bool updateProperty = true, StateObjectPointer pointer = null) { object cachedValue = null; StateObjectSurrogate surrogate = null; if (pointer != null) { if (forSurrogate) { surrogate = (StateObjectSurrogate)pointer.Target; cachedValue = surrogate.Value; } else { var superValuePointer = pointer as StateObjectPointerReferenceSuperValueBase; if (superValuePointer != null) { if (superValuePointer is StateObjectPointerReferenceSuperValue) { cachedValue = superValuePointer.SuperTarget; } else if (superValuePointer is StateObjectPointerReferenceSuperSurrogate) { cachedValue = (superValuePointer.SuperTarget as StateObjectSurrogate).Value; } else if (superValuePointer is StateObjectPointerReferenceSerializable) { cachedValue = superValuePointer.SuperTarget; } if (cachedValue == null) //Reference is pointing to nothing so lets get rid of it { stateManager.RemoveObject(pointer.UniqueID, true); } } else { cachedValue = pointer.Target; if (cachedValue == null) //Reference is pointing to nothing so lets get rid of it { stateManager.RemoveObject(pointer.UniqueID, true); } ///Added to support cases in that the referenced object is a Surrogate else if (cachedValue is StateObjectSurrogate) { surrogate = (StateObjectSurrogate)pointer.Target; cachedValue = surrogate.Value; forSurrogate = true; } } } if (updateProperty) { propEx.OriginalSetter(parentInstance, cachedValue); } if (forSurrogate) { stateManager.AttachBindingBehaviourForSurrogate(surrogate, cachedValue); } } return(cachedValue); }
internal static void ProcessSetterSurrogate(PropertyInfoEx propEx, object parentObject, object newValueObject, bool isNew = false) { //TODO might do direct cast without as. That will be slightly faster var parentInstance = parentObject as IStateObject; var stateManager = StateManager.Current; var uuidgen = stateManager.UniqueIDGenerator; string propName = GetPropertyName(propEx); var relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName); var pointer = (StateObjectPointer)stateManager.GetObject(relativeUid, isNew: isNew); if (newValueObject == null) { //Here we need to remove the surrogate reference if available if (propEx.hasReferenceAttribute) { //However we do no have yet implemented support for Surrogates along with references throw new NotSupportedException(); //TODO } //If there was a value there was a pointer //Surrogates are always accessed thu a pointer if (pointer != null) { //Retrieve surrogate var surrogate = (StateObjectSurrogate)pointer.Target; //Decrease surrogate references //If references drops to 0. Then remove surrogate stateManager.surrogateManager.RemoveSurrogateReference(surrogate, pointer); //Eliminate pointer stateManager.RemoveObject(pointer.UniqueID, true); } } else { bool somethingToDo = true; //Was there a previous value? If there was one then there was a pointer. //If not we need one now. if (pointer == null) { pointer = new StateObjectPointer(); AddDependent(parentInstance, UniqueIDGenerator.REFERENCEPrefix + GetPropertyName(propEx)); StateObjectPointer.AssignUniqueIdToPointer(parentInstance, relativeUid, pointer); } else { //I need to validate that the surrogate is the same and if not decrease reference //First lets see if this is same object var oldsurrogate = (StateObjectSurrogate)pointer.Target; if (oldsurrogate != null) { if (Object.ReferenceEquals(oldsurrogate.Value, newValueObject)) { //Nothing to do somethingToDo = false; } else { //Retrieve surrogate StateObjectSurrogate surrogate = stateManager.surrogateManager.GetSurrogateFor(newValueObject, generateIfNotFound: true); if (surrogate == null) { throw new Exception("Object must be instantiated/registered with resolve"); } //Add reference if needed stateManager.surrogateManager.AddSurrogateReference(surrogate, pointer, false); stateManager.RebindSurrogateReference(oldsurrogate, surrogate, pointer); somethingToDo = false; } } else { throw new InvalidOperationException("Pointer is broken. It should point to an existing surrogate"); } } if (somethingToDo) { //Retrieve surrogate StateObjectSurrogate surrogate = stateManager.surrogateManager.GetSurrogateFor(newValueObject, generateIfNotFound: true); if (surrogate == null) { throw new Exception("Object must be instantiated/registered with resolve"); } //Add reference if needed stateManager.surrogateManager.AddSurrogateReference(surrogate, pointer, false); } } }
public void SendToSurrogatesToBePersisted(StateObjectSurrogate surrogate) { _surrogatesToBePersisted.Add(surrogate); }