コード例 #1
0
        internal static bool ProcessGetterStrongReference(PropertyInfoEx propEx, object parentObject, ref Object lastResult)
        {
            var    prop           = propEx.prop;
            var    parentInstance = parentObject as IStateObject;
            string propName       = GetPropertyName(propEx);
            //Try to recover
            //1. First recover pointer
            //2. Then get surrogate
            string relativeUid  = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);
            var    stateManager = StateManager.Current;
            var    pointer      = (StateObjectPointer)stateManager.GetObject(relativeUid);

            if (pointer != null)
            {
                if (propEx.stateManagementAttribute == StateManagementValues.ServerOnly)
                {
                    stateManager.isServerSideOnly.Add(pointer);
                }
                //Extend to support other types
                var cachedValue = TryToRecoverWithPointer(stateManager, propEx, parentInstance, false, false, pointer: pointer);
                lastResult = cachedValue;
                return(true);
            }
            else
            {
                //There was no pointer, then return null
                lastResult = null;
                return(true);
            }
        }
コード例 #2
0
 internal static bool ProcessGetterTopLevelIStateObject(PropertyInfoEx propEx, object parentObject, ref Object lastValue)
 {
     if (lastValue == null)
     {
         var prop           = propEx.prop;
         var parentInstance = parentObject as IStateObject;
         if (typeof(IStateObject).IsAssignableFrom(prop.DeclaringType))
         {
             Type returnType   = prop.PropertyType;
             var  stateManager = StateManager.Current;
             var  attributes   = returnType.GetCustomAttributes(typeof(Singleton), false);
             if (attributes.Length > 0)
             {
                 var cachedValue = stateManager.GetObject(UniqueIDGenerator.GetSinglentonUniqueId(returnType));
                 lastValue = cachedValue;
                 return(true);
             }
             else
             {
                 var propName    = GetPropertyName(propEx);
                 var relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);
                 var pointer     = (StateObjectPointer)stateManager.GetObject(relativeUid);
                 if (pointer != null)
                 {
                     var cachedValue = TryToRecoverWithPointer(stateManager, propEx, parentInstance, false, pointer: pointer);
                     lastValue = cachedValue;
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
コード例 #3
0
        private static IStateObject GetCurrentValue(StateManager stateManager, PropertyInfoEx propEx, IStateObject parentInstance, out string valueRelativeUid, bool isNew = false)
        {
            var propName = GetPropertyName(propEx);

            valueRelativeUid = UniqueIDGenerator.GetRelativeUniqueID(parentInstance, propName);
            //First Try: Let's get the object from the Storage.
            var currentValue = stateManager.GetObject(valueRelativeUid);

            if (currentValue == null)
            {
                var pointerRelativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);
                //Second try: get the Reference if present.
                currentValue = stateManager.GetObject(pointerRelativeUid, isNew: isNew);
            }
            return(currentValue);
        }
コード例 #4
0
        private static void AddOrUpdateReference(PropertyInfoEx propEx, IStateObject parentInstance, object newValueObj, StateObjectPointerReference currentValue = null, bool isNew = false)
        {
            var    stateManager = StateManager.Current;
            string propName     = GetPropertyName(propEx);
            var    relativeUid  = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);

            var reference = currentValue;

            if (reference == null)
            {
                reference = stateManager.GetObject(relativeUid, isNew: isNew) as StateObjectPointerReference;
            }
            //We need to remove the pointer;
            if (reference != null)
            {
                //	We need to remove the Reference to the value if present and if it's not a
                //StateObjectPointerReferenceSuperValueBase
                if (!(reference is StateObjectPointerReferenceSuperValueBase))
                {
                    stateManager.ReferencesManager.RemoveReference(reference, reference.Target);
                }
                // Let's check if the existing reference is compatible with the newValue to
                //remove it or if the value being set is null as well.
                if (newValueObj == null || !reference.IsCompatibleWith(newValueObj))
                {
                    //If the Reference is not compatible then we need to remove it to get a new one.
                    stateManager.RemoveObject(relativeUid, true);
                    reference = null;
                }
            }
            //Only if the newValue is not null we need a reference, otherwise lets avoid the overhead.
            if (newValueObj != null && reference == null)
            {
                //Gets the reference for the property.
                reference = GetReference(propEx, parentInstance, newValueObj);
            }
            //No reference, no value...We don't need to do anything else.
            else if (newValueObj == null && reference == null)
            {
                return;
            }

            //Once we got the Reference let's update it.
            UpdateReferenceValue(stateManager, reference, parentInstance, newValueObj);
        }
コード例 #5
0
 internal static bool ProcessGetterSurrogate(PropertyInfoEx propEx, object parentObject, ref Object lastResult)
 {
     if (lastResult == null)
     {
         var    prop           = propEx.prop;
         var    parentInstance = parentObject as IStateObject;
         Type   returnType     = prop.PropertyType;
         string propName       = GetPropertyName(propEx);
         //Try to recover
         //1. First recover pointer
         //2. Then get surrogate
         string relativeUid  = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);
         var    stateManager = StateManager.Current;
         var    pointer      = (StateObjectPointer)stateManager.GetObject(relativeUid);
         if (pointer != null)
         {
             var cachedValue = TryToRecoverWithPointer(stateManager, propEx, parentInstance, true, pointer: pointer);
             lastResult = cachedValue;
             return(true);
         }
     }
     return(false);
 }
コード例 #6
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);
        }
コード例 #7
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);
                    }
                }
            }
        }
コード例 #8
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);
        }
コード例 #9
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);
                }
            }
        }