public void NotifyChanged(ModelRepresentation representation) { lock (changeLock) { lastChangedRepresentation = representation; representation.CurrentVersion = ++changeVersion; } RaiseChangedEvent(representation.GetType()); }
public void NotifyHasUnsavedChanges(ModelRepresentation representation) { var repType = representation.GetType(); foreach (var m in linkedModels) { if (m.RepresentationType == repType) { m.RaiseHasUnsavedChangesEvent(); } } }
async Task Synchronize(ModelRepresentation targetRep, bool dataLocked) { ModelRepresentation sourceModel = null; int currentChangeVersion; lock (changeLock) { sourceModel = lastChangedRepresentation; currentChangeVersion = changeVersion; } if (targetRep.CurrentVersion == currentChangeVersion || sourceModel == null || sourceModel == targetRep) { return; // Not changed } try { // Any operation that requires the lock of several representation must take // the model lock first, to avoid deadlocks if (!dataLocked) { await dataLock.WaitAsync(); await targetRep.WaitHandle.WaitAsync(); await sourceModel.WaitHandle.WaitAsync(); } await targetRep.InternalCopyFrom(sourceModel); } finally { if (!dataLocked) { dataLock.Release(); targetRep.WaitHandle.Release(); sourceModel.WaitHandle.Release(); } } RaiseChangedEvent(targetRep.GetType()); }
internal async Task Relink(DocumentModel model, DocumentModelData newData) { bool newDataLocked = false, representationLocked = false; ModelRepresentation representation = null; var repType = model.RepresentationType; ModelRepresentation modelRepresentationToDispose = null; var modelsToNotify = new List <DocumentModel> (); await dataLock.WaitAsync(); try { representations.TryGetValue(repType, out representation); await representation.WaitHandle.WaitAsync(); representationLocked = true; linkedModels = linkedModels.Remove(model); var modelsForRep = linkedModels.Where(m => m.RepresentationType == repType).ToList(); if (modelsForRep.Count > 0) { // If there is more than one model using this representation then the representation // has to be cloned, since it can't be shared anymore var representationCopy = (ModelRepresentation)Activator.CreateInstance(representation.GetType()); await representationCopy.InternalCopyFrom(representation); representationCopy.DocumentModelData = this; representations [repType] = representationCopy; foreach (var m in modelsForRep) { modelsToNotify.Add(m); } } else { await RemoveRepresentation(repType, representation); } if (newData != null) { await newData.dataLock.WaitAsync(); newDataLocked = true; // If there are other models using the same representation, we'll have to notify them that // the representation has changed if (newData.representations.TryGetValue(repType, out modelRepresentationToDispose)) { modelsToNotify.AddRange(newData.linkedModels.Where(m => m.RepresentationType == repType)); } newData.linkedModels = newData.linkedModels.Add(model); model.Data = newData; newData.representations [repType] = representation; representation.DocumentModelData = newData; // Register that this new representation is the latest version. // If there are other representations, they will get the new data after a Synchronize call. newData.NotifyChanged(representation); } } finally { dataLock.Release(); if (representationLocked) { representation.WaitHandle.Release(); } if (newDataLocked) { newData.dataLock.Release(); } } foreach (var m in modelsToNotify) { m.RaiseRepresentationChangeEvent().Ignore(); } if (modelRepresentationToDispose != null) { modelRepresentationToDispose.OnDispose().Ignore(); } }
protected override async Task OnCopyFrom(ModelRepresentation other) { if (other is FileModelRepresentation file) { await SetContent(file.GetContent()); } else { throw new InvalidOperationException($"Can't copy data from model of type {other.GetType ()} into a model of type {GetType ()}"); } }