internal static void AssignUniqueIdToPointer(IStateObject parentInstance, string relativeUid,
                                                     StateObjectPointer pointer)
        {
            var stateManager = StateManager.Current;

            if (StateManager.AllBranchesAttached(parentInstance))
            {
                //at this point we have a new pointer with an attached parent
                //which means that it was born on the temp stateManager
                //we cannot just do a switchunique ids because switching
                //is only on the stateManager level
                //we need to promote it from temp to StateManager
                //to make sure that it will be persisted
                pointer.UniqueID = relativeUid;
                stateManager.AddNewAttachedObject(pointer);
            }
            else
            {
                //at this point we have a new pointer with an UNATTACHED parent
                //which means both the parent and the pointer are on the temp stateManager
                //we need to switchunique ids because
                //they are at the stateManager level
                //if the parent is promoted so will be the pointer
                pointer.UniqueID = relativeUid;
                stateManager.AddNewTemporaryObject(pointer);
            }
        }
 /// <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);
 }
 /// <summary>
 /// Replaces the surrogate pointer references from one pointer to another.  This method is called
 /// every time a pointer is promoted because its parent object has been attached to a view model object.
 /// </summary>
 /// <param name="pointerOldUniqueId">Unique id of the object that was not attached.</param>
 /// <param name="pointerNewUniqueId">Uniqued Id of the object pointer once attached.</param>
 public void UpdateDependantSurrogatePointerReferences(string pointerOldUniqueId, string pointerNewUniqueId, IStateObject value)
 {
     // lets check if it is a pointer if it is registered as surrogate object pointer.
     if (value != null && UniqueIDGenerator.IsPointer(pointerOldUniqueId))
     {
         StateObjectPointer ptr = (StateObjectPointer)value;
         var surrogate          = ptr.Target as StateObjectSurrogate;
         if (surrogate != null)
         {
             lock (surrogate)
             {
                 foreach (var objectRef in surrogate.objectRefs)
                 {
                     if (objectRef.UniqueID == pointerOldUniqueId)
                     {
                         objectRef.UniqueID = pointerNewUniqueId;
                     }
                 }
             }
         }
     }
 }
Пример #4
0
        internal static EventPromiseInfo BuildContinuationInfo(StateManager stateManager, EventPromiseInfo promise, Delegate code, IStateObject parent = null, string promiseUniqueId = null, string actionID = "")
        {
            var  instance        = code.Target;
            Type codePromiseType = instance != null?instance.GetType() : null;

            string internalFieldsState = null;

            //This variable holds the reference
            //to the IStateObject that is closest to the promise.
            //For example if we are referring to a method on a Form. The closest state object is a
            //ViewModel. If the object is a DisplayClass, then we try to determine
            //which was the closest IModel or IUserControl where this DisplayClass was used
            IStateObject objectContainingMethod = null;

            if (codePromiseType != null)
            {
                //For special classes it's required to register a surrogate to save the application state.
                if (TypeCacheUtils.IsSpecialClass(codePromiseType))
                {
                    PromiseUtils.RegisterSurrogateForDisplayClass(codePromiseType, code.Target);
                    objectContainingMethod = stateManager.surrogateManager.GetSurrogateFor(code.Target, generateIfNotFound: true);
                }
                else
                {
                    var stateObject = instance as IStateObject;
                    if (stateObject != null)
                    {
                        objectContainingMethod = stateObject;
                    }
                    else
                    {
                        var logicView = instance as ILogicView <IViewModel>;
                        if (logicView != null)
                        {
                            objectContainingMethod = logicView.ViewModel;
                        }
                    }
                }
            }

            string methodArgs = null;
            var    parameters = code.Method.GetParameters();

            if (parameters.Length > 0)
            {
                StringBuilder builder = new StringBuilder();
                foreach (var parameter in parameters)
                {
                    builder.Append(parameter.ParameterType.AssemblyQualifiedNameCache());
                    builder.Append("|");
                }
                methodArgs = builder.ToString();
            }

            promise.DeclaringType = code.Method.DeclaringType.AssemblyQualifiedNameCache();
            //promise.SetObjectContainingMethod(objectContainingMethod);
            promise.TargetType = code.Target != null?code.Target.GetType().AssemblyQualifiedNameCache() : null;

            promise.MethodName = code.Method.Name;
            promise.ActionID   = actionID;
            promise.ParentId   = parent != null ? parent.UniqueID :
                                 promise.ModalUniqueId = null;
            promise.MethodArgs = methodArgs;
            promise.UniqueID   = promiseUniqueId ??
                                 (parent == null
                                   ? stateManager.UniqueIDGenerator.GetPromiseUniqueID()
                                   : stateManager.UniqueIDGenerator.GetRelativeUniqueID(parent));
            promise.ContinuationFields = internalFieldsState;
            promise.DelegateType       =
                TypeCacheUtils.GetDelegateTypeBasedOnMethodParameters(code.Method).AssemblyQualifiedNameCache();

            stateManager.AddNewObject(promise);

            if (objectContainingMethod != null)
            {
                if (!StateManager.AllBranchesAttached(objectContainingMethod))
                {
                    stateManager.AdoptionInformation.RegisterPossibleOrphan(promise, objectContainingMethod);
                }

                var referenceToObjectContainingMethod = new StateObjectPointerReference();
                var relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(promise, "PO");
                LazyBehaviours.AddDependent(promise, UniqueIDGenerator.REFERENCEPrefix + "PO");
                StateObjectPointer.AssignUniqueIdToPointer(promise, relativeUid, referenceToObjectContainingMethod);
                referenceToObjectContainingMethod.Target = objectContainingMethod;
                stateManager.isServerSideOnly.Add(referenceToObjectContainingMethod);
                stateManager.AddNewObject(referenceToObjectContainingMethod);
                stateManager.ReferencesManager.AddReference(referenceToObjectContainingMethod, objectContainingMethod);
                var surrogate = objectContainingMethod as StateObjectSurrogate;
                if (surrogate != null)
                {
                    stateManager.surrogateManager.AddSurrogateReference(surrogate, referenceToObjectContainingMethod);
                }

                promise.SetObjectContainingMethod(referenceToObjectContainingMethod);
            }
            if (parent != null && objectContainingMethod != null && parent.Equals(objectContainingMethod))
            {
                promise.isLocalInstance = true;
            }
            else
            if (promiseUniqueId != null && objectContainingMethod != null)
            {
                var parentUniqueID = StateManager.GetLastPartOfUniqueID(promise);
                promise.isLocalInstance = string.Equals(parentUniqueID, objectContainingMethod.UniqueID);
            }

            return(promise);
        }
Пример #5
0
        object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            StateObjectPointer pointer = (StateObjectPointer)existingValue;

            reader.Read();
            var propertyName = reader.Value.ToString();

            if (propertyName == "p")
            {
                var uniqueIdforReferencedObject = reader.ReadAsString();
                pointer._targetUniqueId = uniqueIdforReferencedObject;
                return(pointer);
            }
            if (propertyName == "d")
            {
                reader.Read();
                var value = serializer.Deserialize(reader);
                ((StateObjectPointerReferenceSerializable)pointer).SuperTarget = value;
                return(pointer);
            }
            if (propertyName == "v" || propertyName == "u")
            {
                reader.Read();
                var type = TypeCacheUtils.GetType(reader.ReadAsString());
                if (type == typeof(object))
                {
                    return(new StateObjectPointerReferenceSuperValue());
                }
                else
                {
                    var    str   = reader.ReadAsString();
                    object value = null;
                    if (type.IsEnum)
                    {
                        value = Enum.Parse(type, str, true);
                    }
                    else if (typeof(decimal) == type)
                    {
                        value = decimal.Parse(str, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
                    }
                    else if (typeof(double) == type)
                    {
                        value = double.Parse(str, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        if (TypeCacheUtils.IsAnUserStructType(type))
                        {
                            value = JsonConvert.DeserializeObject(str, type);
                        }
                        else
                        {
                            value = System.Convert.ChangeType(str, type);
                        }
                    }

                    ((StateObjectPointerReferenceSuperValue)pointer).SuperTarget = value;
                    return(pointer);
                }
            }
            if (propertyName == "s")
            {
                //TODO surrogate
                var uniqueIDSurrogate = reader.ReadAsString();
                var superSurrogate    = pointer as StateObjectPointerReferenceSuperSurrogate;
                superSurrogate._targetSurrogateUniqueId = uniqueIDSurrogate;
                return(pointer);
            }

            throw new NotSupportedException();
        }
Пример #6
0
        internal static void ProcessSetterWeakReference(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;
            string propName       = GetPropertyName(propEx);


            //Implementation of StateObject Reference
            //In this case the setter is never really used.
            //it is always intercepted
            var relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);
            var pointer     = (StateObjectPointerReference)stateManager.GetObject(relativeUid, isNew: isNew);

            if (newValueObject == null)
            {
                if (pointer != null)
                {
                    //We need to remove the pointer;
                    stateManager.RemoveObject(relativeUid, true);
                }
                //if newValue == null and pointer == null there is nothing to do
            }
            else             //New value is not null then
            {
                //did we have a value?
                if (pointer == null)
                {
                    AddDependent(parentInstance, UniqueIDGenerator.REFERENCEPrefix + GetPropertyName(propEx));
                    //If not create one
                    if (propEx.isStateObject || propEx.isAnIList || propEx.isAnIDictionary)
                    {
                        pointer = new StateObjectPointerReference();
                        if (propEx.stateManagementAttribute == StateManagementValues.ServerOnly)
                        {
                            stateManager.isServerSideOnly.Add(pointer);
                        }
                    }
                    else if (propEx.isNonStateObjectFixedType)
                    {
                        pointer = new StateObjectPointerReferenceSuperValue();
                    }
                    else
                    {
                        var stackTrace = new StackTrace(3, true);
                        throw new InvalidOperationException(
                                  "LazyBehaviour::ProcessSetter Property with reference attribute receive a value of unsupported type.\r\n" +
                                  "Additional Info: \r\n" +
                                  "Value Type: " + newValueObject.GetType().FullName + "\r\n" +
                                  "Property Type: " + propName + "\r\n" +
                                  "Error Location: " + stackTrace);
                    }
                    //Surrogates are handled above

                    StateObjectPointer.AssignUniqueIdToPointer(parentInstance, relativeUid, pointer);
                }
                var pointerReferenceSuperValue = pointer as StateObjectPointerReferenceSuperValue;
                var tracker = stateManager.Tracker;
                if (pointerReferenceSuperValue != null)
                {
                    pointerReferenceSuperValue.SuperTarget = newValueObject;
                    tracker.MarkAsModified(pointerReferenceSuperValue, "Target");
                }
                else
                {
                    var newValue = newValueObject as IStateObject;
                    //Once we have a pointer make the newValue its new target
                    pointer.Target = newValue;
                    tracker.MarkAsModified(pointer, "Target");


                    // Here we will try to manage posible orphans assigned to Pointers
                    if (!StateManager.AllBranchesAttached(newValue))
                    {
                        stateManager.AdoptionInformation.RegisterPossibleOrphan(parentInstance, newValue, godparent: pointer);
                    }
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Gets a Reference for an specified value and property.
        /// </summary>
        /// <param name="propEx">The property associated to the value being set.</param>
        /// <param name="parentInstance">The parent instance of the property</param>
        /// <param name="newValueObject">The new value for the property.</param>
        /// <returns></returns>
        private static StateObjectPointerReference GetReference(PropertyInfoEx propEx, IStateObject parentInstance, object newValueObject)
        {
            StateObjectPointerReference reference = null;
            string name        = GetPropertyName(propEx);
            var    relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, name);

            AddDependent(parentInstance, UniqueIDGenerator.REFERENCEPrefix + name);
            //Let's try to cast the element to IStateObject
            var newValue = newValueObject as IStateObject;

            //It's an IList, IDisctionary or an IStateObject or the Value is an IStateObject
            if (propEx.isStateObject || propEx.isAnIList || propEx.isAnIDictionary || newValue != null)
            {
                reference = new StateObjectPointerReference();
            }
            //It's a value type or type.
            else if (propEx.isNonStateObjectFixedType)
            {
                reference = new StateObjectPointerReferenceSuperValue();
            }
            //It's declared as an Object.
            else if (propEx.isObjectPropertyType)
            {
                var newValueType = newValueObject.GetType();
                //If the Value is an IStateObject
                if (newValueType.IsValueType || newValueType == typeof(string) || newValueType == typeof(Type))
                {
                    if (TypeCacheUtils.IsAnUserStructType(propEx.prop.PropertyType))
                    {
                        reference = new StateObjectPointerReferenceSuperStruct();
                    }
                    else
                    {
                        reference = new StateObjectPointerReferenceSuperValue();
                    }
                }
                //It's a registered surrogated.
                else if (SurrogatesDirectory.IsSurrogateRegistered(newValueType))
                {
                    reference = new StateObjectPointerReferenceSuperSurrogate();
                }
                else
                {
                    reference = new StateObjectPointerReferenceSerializable();
                }
            }
            else             //Not supported type
            {
                var stackTrace = new StackTrace(3, true);
                throw new InvalidOperationException(
                          "LazyBehaviour::ProcessSetter Property with reference attribute receive a value of unsupported type.\r\n" +
                          "Additional Info: \r\n" +
                          "Value Type: " + propEx.prop.PropertyType.FullName + "\r\n" +
                          "Property Type: " + GetPropertyName(propEx) + "\r\n" +
                          "Error Location: " + stackTrace);
            }
            //If it has the StateManagement attribute set as ServerOnly, then let's respect that.
            if (propEx.stateManagementAttribute == StateManagementValues.ServerOnly)
            {
                StateManager.Current.isServerSideOnly.Add(reference);
            }
            //Let's set the UniqueID to the new reference.
            StateObjectPointer.AssignUniqueIdToPointer(parentInstance, relativeUid, reference);
            //Let's return the pointer of the desired type.
            return(reference);
        }
Пример #8
0
        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);
                }
            }
        }
Пример #9
0
        /// <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);
        }