internal static bool ProcessGetterNonTopLevelIStateObject(PropertyInfoEx propEx, object parentObject, ref Object lastResult) { //Here we need to introduce an exception. //We can have a property that has a PropertyType that is NOT an IStateObject //for example an IList //We have taken the decision that all IList<SomeObjectThatImplementsIStateObject> //will have an implementation class that is an IStateObject //so we need to add that check object cachedValue = lastResult; //propEx.OriginalGetter(parentObject); bool result = false; //If the cached value is null or it's a reference, we need to try to get it again. if (cachedValue == null) { var parentInstance = parentObject as IStateObject; var stateManager = StateManager.Current; string relaviteUID = null; cachedValue = GetCurrentValue(stateManager, propEx, parentInstance, out relaviteUID); if (cachedValue is StateObjectPointerReference) { cachedValue = TryToRecoverWithPointer(stateManager, propEx, parentInstance, false, false, pointer: (StateObjectPointerReference)cachedValue); } else { //If the value Tagged as server side only? //We must track because it could also be assigned into lists, dictionaries or references if (cachedValue != null) { if (propEx.stateManagementAttribute == StateManagementValues.ServerOnly) { stateManager.isServerSideOnly.Add((IStateObject)cachedValue); } var events = ViewManager.Instance.Events; try { events.Suspend(); propEx.OriginalSetter(parentObject, cachedValue); } finally { events.Resume(); } } } lastResult = cachedValue; result = true; } return(result); }
/// <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); }