示例#1
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);
                    }
                }
            }
        }
示例#2
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);
        }