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); } } }
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); }
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); } }
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); } }
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); }
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); } } }