private static void SerializeFields(StateManager stateManager, object instance, ref IStateObject viewModel, BinaryWriter writer, Type logicObjectType, IList <FieldInfo> fieldList, string fieldPrefix = "")
        {
            var formatter = new BinaryFormatter();

            foreach (var field in fieldList)
            {
#if DEBUG
                Trace.WriteLine(string.Format("Serializing promise field {0}.{1}", fieldPrefix, field.Name));
#endif
                var objValue = field.GetValue(instance);
                if (objValue == null)
                {
                    continue;                   //We do not need to save null fields
                }
                ///The delegate can be an instance method. We are looking to determine if there is a reference to the "this instance"
                if (IsThisTheThisField(stateManager, instance, field, logicObjectType, objValue, writer, fieldPrefix, ref viewModel))
                {
                    continue;
                }
                if (field.Name.Contains("locals"))
                {
                    var parentSurrogate = stateManager.surrogateManager.GetSurrogateFor(instance, generateIfNotFound: false);
                    if (parentSurrogate == null)
                    {
                        throw new InvalidOperationException("A parent surrogate is needed");
                    }
                    var localsSurrogate = stateManager.surrogateManager.GetSurrogateFor(objValue, generateIfNotFound: false);
                    if (localsSurrogate == null) //There was not a previous surrogate!! Ok we need a lastminute one
                    {
                        throw new Exception("Invalid condition. Surrogate dependency should have been reported previously");
                        //RegisterSurrogateForDisplayClass(field.FieldType, objValue,parentSurrogate.UniqueID);

                        //localsSurrogate = stateManager.surrogateManager.GetSurrogateFor(objValue, generateIfNotFound: true, parentSurrogate: parentSurrogate.UniqueID);
                        //stateManager.surrogateManager.AddSurrogateReference(localsSurrogate, parentSurrogate.UniqueID);
                    }
                    writer.Write(field.Name);
                    writer.Write(localsSurrogate.UniqueID);
                    continue;
                }
                //If we have a value we need to serialize
                //We will write the fieldName + Value
                bool isSerializable = false;
                if (objValue is IStateObject || IsInterfaceThatMightBeAnStateObject(objValue))
                {
                    //For IStateObject only the UniqueID is needed for the other we would use the ISerialize
                    var value = (IStateObject)objValue;
                    //If this field is not the this then we are goint to save its value
                    writer.Write(fieldPrefix + field.Name);
                    var orphanHolder = stateManager.AdoptionInformation.GetOrphanHolder(instance, value, field.Name);
                    if (orphanHolder == null)
                    {
                        writer.Write(value.UniqueID);
                    }
                    else
                    {
                        writer.Write(orphanHolder.UniqueID);
                    }
                }
                else if (objValue is ILogicWithViewModel <IStateObject> )
                {
                    var value = (ILogicWithViewModel <IStateObject>)objValue;
                    Debug.Assert(value.ViewModel != null);
                    writer.Write(fieldPrefix + field.Name);
                    writer.Write(value.ViewModel.UniqueID);
                }
                else if ((isSerializable = (field.FieldType.IsSerializable || objValue.GetType().IsSerializable)) && objValue is MulticastDelegate)
                {
                    SerializeDelegate(stateManager, instance, writer, fieldPrefix, field, objValue);
                }
                else if (SurrogatesDirectory.IsSurrogateRegistered(field.FieldType))
                {
                    var surrogate = stateManager.surrogateManager.GetSurrogateFor(objValue, generateIfNotFound: true);
                    if (surrogate == null)
                    {
                        // Something is wrong here, throw an exception
                        throw new InvalidOperationException("Error getting the surrogate for field " + field.Name + " with type " + field.FieldType.FullName + " inside object of type " + instance.GetType().FullName);
                    }
                    var parentSurrogate = stateManager.surrogateManager.GetSurrogateFor(instance, generateIfNotFound: false);
                    stateManager.surrogateManager.AddSurrogateReference(surrogate, parentSurrogate);
                    writer.Write(field.Name);
                    writer.Write(surrogate.UniqueID);
                }
                else if (isSerializable)
                {
                    writer.Write(fieldPrefix + field.Name);
                    formatter.Serialize(writer.BaseStream, objValue);
                }
                else
                {
                    throw new NotSupportedException("Error serializing field " + field.Name + " with type " + field.FieldType.FullName + " inside object of type " + instance.GetType().FullName);
                }
            }
        }
Example #2
0
        public IList <IStateObject[]> ExtractOrphansWithQualifiedParents()
        {
            List <IStateObject[]> result = new List <IStateObject[]>();

            foreach (var orphan in orphanInformationTables.orphanToParentCandidates)
            {
                if (orphan.Key is IDependentViewModel)
                {
                    var          parentList = orphan.Value;
                    IStateObject firstNonVisualParentCandidate = null;;
                    IStateObject firstVisualParentCandidate    = null;
                    foreach (var parent in parentList)
                    {
                        if (StateManager.AllBranchesAttached(parent))
                        {
                            if (parent is IModel || parent is IDependentModel || parent is IStateObjectSurrogate)
                            {
                                firstNonVisualParentCandidate = parent;
                                continue;
                            }
                            if (parent is IViewModel || parent is IDependentViewModel)
                            {
                                firstVisualParentCandidate = parent;
                                break;
                            }
                        }
                    }
                    if (firstVisualParentCandidate != null)
                    {
                        result.Add(new[] { orphan.Key, firstVisualParentCandidate });
                    }
                    else if (firstNonVisualParentCandidate != null)
                    {
                        result.Add(new[] { orphan.Key, firstNonVisualParentCandidate });
                    }
                }
                else
                {
                    var parentList = orphan.Value;
                    foreach (var parent in parentList)
                    {
                        if (StateManager.AllBranchesAttached(parent))
                        {
                            result.Add(new[] { orphan.Key, parent });
                            break;
                        }
                    }
                }
            }
            foreach (var pairs in result)
            {
                orphanInformationTables.orphanToParentCandidates.Remove(pairs[0]);
            }
            if (result.Count > 0)
            {
                //We sort this list to make sure that children adoptions occur before parent adoptions
                result.Sort((x, y) => {
                    if (x == null)
                    {
                        return(-1);
                    }
                    if (y == null)
                    {
                        return(1);
                    }
                    return(CompareOrphans(x[0], y[0]));
                });
            }
            return(result);
        }
Example #3
0
        public static void StaticAdopt(IStateObject parent, IStateObject orphan)
        {
            var referencesManager = StateManager.Current.ReferencesManager;
            //We will try to adopt the parent of an object if it has references, thats why first we need to calculate the parents with References.
            var orphansStack = new List <IStateObject>();
            //Candidates Stack.
            var candidatesStack = new List <IStateObject>();

            if (!StateManager.AllBranchesAttached(orphan))
            {
                //Let's try to calculate the posible parent of the orphan.
                var orphanCandidate = referencesManager.GetCandidateForAdoption(orphan, isHandlingOrphans: true);
                var isOphanCandidateAGoodCandidate = false;
                var isParentAGoodCandidate         = false;
                if (orphanCandidate is IViewModel || orphanCandidate is IDependentViewModel)
                {
                    isOphanCandidateAGoodCandidate = true;
                }
                if (parent is IViewModel || parent is IDependentViewModel)
                {
                    isParentAGoodCandidate = true;
                }
                //The first and maybe the only element in the Stack is the Orphan, but
                //only if has a valid adoption candidate.
                if (orphanCandidate != null)
                {
                    orphansStack.Add(orphan);
                    //We will always prefer the candidate coming from the ReferencesManager
                    if (isOphanCandidateAGoodCandidate)
                    {
                        candidatesStack.Add(orphanCandidate);
                    }
                    //If neither both possible candidates is not a good candidates, we will also prefer the one coming from the references manager.
                    else if (!isParentAGoodCandidate && !isOphanCandidateAGoodCandidate)
                    {
                        candidatesStack.Add(orphanCandidate);
                    }
                    //This is the lowest preference
                    else
                    {
                        candidatesStack.Add(parent);
                    }
                }
                else
                //The adoption won't continue because the orphan doesn't have any valid candidate for adoption.
                {
                    ProcessStaticAdoption(parent, orphan);
                    return;
                }

                var orphanParent = StateManager.Current.GetParentEx(orphan);
                while (orphanParent != null)
                {
                    //If the parent has References, then we add it to the orphans Stack.
                    if (referencesManager.HasReferences(orphanParent))
                    {
                        var parentCandidate = referencesManager.GetCandidateForAdoption(orphanParent);
                        if (parentCandidate != null)
                        {
                            orphansStack.Add(orphanParent);
                            candidatesStack.Add(parentCandidate);
                        }
                    }
                    orphanParent = StateManager.Current.GetParentEx(orphanParent);
                }
                //From the candidates in the Tree let's get the best one.
                IStateObject currCandidate = candidatesStack[candidatesStack.Count - 1];
                //for (int i = candidatesStack.Count - 1; i >= 0; i--)
                //{
                //    //Only if the paren't element is not visual let's try to find a better candidate.
                //    if (candidatesStack[i] is IViewModel || candidatesStack[i] is IDependentViewModel)
                //    {
                //        currCandidate = candidatesStack[i];
                //        break;
                //    }
                //}
                var orphanToAdopt = orphansStack[orphansStack.Count - 1];
                ProcessStaticAdoption(currCandidate, orphanToAdopt);
            }
        }
Example #4
0
        private void Adopt(IStateObject parent, IStateObject orphan)
        {
            var referencesManager = _stateManager.ReferencesManager;
            //We will try to adopt the parent of an object if it has references, thats why first we need to calculate the parents with References.
            var orphansStack = new List <IStateObject>();
            //Candidates Stack.
            var candidatesStack = new List <IStateObject>();

            if (!StateManager.AllBranchesAttached(orphan))
            {
                //Let's try to calculate the posible parent of the orphan.
                var orphanCandidate = referencesManager.GetCandidateForAdoption(orphan, isHandlingOrphans: true);
                var isOphanCandidateAGoodCandidate = false;
                var isParentAGoodCandidate         = false;
                if (orphanCandidate is IViewModel || orphanCandidate is IDependentViewModel)
                {
                    isOphanCandidateAGoodCandidate = true;
                }
                if (parent is IViewModel || parent is IDependentViewModel)
                {
                    isParentAGoodCandidate = true;
                }
                //The first and maybe the only element in the Stack is the Orphan, but
                //only if has a valid adoption candidate.
                if (orphanCandidate != null)
                {
                    orphansStack.Add(orphan);
                    //We will always prefer the candidate coming from the ReferencesManager
                    if (isOphanCandidateAGoodCandidate)
                    {
                        candidatesStack.Add(orphanCandidate);
                    }
                    //If neither both possible candidates is not a good candidates, we will also prefer the one coming from the references manager.
                    else if (!isParentAGoodCandidate && !isOphanCandidateAGoodCandidate)
                    {
                        candidatesStack.Add(orphanCandidate);
                    }
                    //This is the lowest preference
                    else
                    {
                        candidatesStack.Add(parent);
                    }
                }
                else
                //The adoption won't continue because the orphan doesn't have any valid candidate for adoption.
                {
                    ProcessAdoption(parent, orphan);
                    return;
                }
                IStateObject           orphanParent;
                var                    orphanParentIterator = orphanParent = _stateManager.GetParentEx(orphan);
                HashSet <IStateObject> visitedParents       = new HashSet <IStateObject>();
                //Cyclyc referernces are causing infinite loops.
                while (orphanParentIterator != null && !visitedParents.Contains(orphanParentIterator))
                {
                    //If the parent has References, then we add it to the orphans Stack.
                    if (referencesManager.HasReferences(orphanParentIterator))
                    {
                        var parentCandidate = referencesManager.GetCandidateForAdoption(orphanParentIterator, isHandlingOrphans: true);
                        if (parentCandidate != null)
                        {
                            orphansStack.Add(orphanParentIterator);
                            candidatesStack.Add(parentCandidate);
                        }
                    }
                    visitedParents.Add(orphanParentIterator);
                    orphanParentIterator = _stateManager.GetParentEx(orphanParentIterator);
                }
                //From the candidates in the Tree let's get the best one.
                IStateObject currCandidate = candidatesStack[candidatesStack.Count - 1];
                var          orphanToAdopt = orphansStack[orphansStack.Count - 1];

                ProcessAdoption(currCandidate, orphanToAdopt);
            }
        }
Example #5
0
            public int Compare(OrphanInfoEntry x, OrphanInfoEntry y)
            {
                var xUid = x.Parent.UniqueID;
                var yUid = y.Parent.UniqueID;

                if (StateManager.IsAttached(x.Parent))
                {
                    if (StateManager.IsAttached(y.Parent))
                    {
                        if (x.Godparent == null && y.Godparent == null)
                        {
                            if (xUid.Length > yUid.Length)
                            {
                                return(1);
                            }
                            if (xUid.Length < yUid.Length)
                            {
                                return(-1);
                            }
                            return(0);
                        }
                        if (x.Godparent == null)
                        {
                            return(-1);
                        }
                        if (y.Godparent == null)
                        {
                            return(1);
                        }

                        if (x.Godparent.UniqueID.Length > y.Godparent.UniqueID.Length)
                        {
                            return(1);
                        }
                        if (x.Godparent.UniqueID.Length < y.Godparent.UniqueID.Length)
                        {
                            return(-1);
                        }
                        return(0);
                    }
                    return(-1);
                }

                if (!StateManager.IsAttached(y.Parent))
                {
                    if (x.Godparent == null)
                    {
                        return(1);
                    }
                    if (y.Godparent == null)
                    {
                        return(-1);
                    }

                    if (x.Godparent.UniqueID.Length > y.Godparent.UniqueID.Length)
                    {
                        return(1);
                    }
                    if (x.Godparent.UniqueID.Length < y.Godparent.UniqueID.Length)
                    {
                        return(-1);
                    }
                    return(0);
                }
                return(1);
            }
Example #6
0
        private static void InitializeObject(StateManager stateManager, IIocContainer container, ILogic logic, object[] parameters, Type logicType, bool isRecoveredFromStorage, IIocContainerFlags flags)
        {
            var  isNewLogic = true;
            bool autoWired  = false;
            bool isNoView   = false;

            //Was this an ILogicView<T>
            if (logic is ILogicView <IViewModel> )
            {
                IViewModel viewModel = null;
                isNoView = (flags & IIocContainerFlags.NoView) == IIocContainerFlags.NoView;
                //Do we need to create a view for this logic object???
                if (isNoView)
                {
                    isNewLogic = false;
                }
                else
                {
                    PropertyInfo viewModelProp = logicType.Property("ViewModel");                     //This type is fix but arbitrary
                    //Is there a view parameter? it should be the first one. If not we will consider that is a constructor parameter
                    if (parameters != null && parameters.Length > 0 && parameters[0] is IViewModel)
                    {
                        viewModel = (IViewModel)parameters[0];
                        //In case we are providing aditional parameter it determines if the logic instance is new
                        //this case can't be determine within the this method so it needs to be passed as an aditional value in the parameters
                        isNewLogic = parameters.Length > 1 ? (bool)parameters[1] : false;
                    }
                    else
                    {                       //Ok. We still dont have a view so we need to create one. We require the property to get the actual PropertyType of the logic
                        viewModel = (IViewModel)container.Resolve(viewModelProp.PropertyType);
                        try
                        {
                            ViewManager.Instance.Events.Suspend();
                            viewModel.Build(container);
                        }
                        finally
                        {
                            ViewManager.Instance.Events.Resume();
                        }
                    }
                    viewModelProp.SetValue(logic, viewModel, null);
                    if (!isRecoveredFromStorage)
                    {
                        autoWired = true;
                        ViewManager.Instance.Events.AutoWireEvents(logic);
                    }
                }
            }
            // lets inject the container
            if (logic is ICreatesObjects)
            {
                ((ICreatesObjects)logic).Container = container;
            }
            if (logic is IInteractsWithView)
            {
                ((IInteractsWithView)logic).ViewManager = ViewManager.Instance;
            }

            if (!isRecoveredFromStorage)
            {
                // lets inject all IViewModel properties
                if (logic is IStateObject)
                {
                    InitializeObject(stateManager, container, (IStateObject)logic, parameters, logicType, flags);
                    //Only Visual objects need autowire.
                    if (!autoWired && logic is IDependentViewModel)
                    {
                        ViewManager.Instance.Events.AutoWireEvents(logic);
                    }
                }
                if (isNewLogic)
                {
                    if ((flags & IIocContainerFlags.ExtraLean) != IIocContainerFlags.ExtraLean)
                    {
                        InitializationHelpers.CallInitializeCommon(logic, logicType);
                    }
                    //First we check to avoid unnecessary calls to GetInitMethod
                    if (logic is IInitializable && !isRecoveredFromStorage && !isNoView && ((flags & IIocContainerFlags.Lean) != IIocContainerFlags.Lean))
                    {
                        //Get Init must be done on the instance type, because logicType might refer to an interface
                        InitializationHelpers.CallInitMethod((IInitializable)logic, parameters);
                    }
                }
            }
            else
            {
                var dict = logic as IObservableDictionaryEntries;
                if (dict != null)
                {
                    dict.Initialize(stateManager, stateManager.ReferencesManager, stateManager.surrogateManager);
                }
            }
        }