private ChangePacket createChangePacket(IModelObject obj, ModelChange change) { // Clear buffers keys.Clear(); values.Clear(); var p = new ChangePacket(); p.Change = change; p.Guid = getObjectGuid(obj); p.TypeFullName = TW.Data.TypeSerializer.Serialize(obj.GetType()); foreach (var att in ReflectionHelper.GetAllAttributes(obj.GetType())) { var data = att.GetData(obj); if (data != null && Attribute.GetCustomAttribute(data.GetType(), typeof(NoSyncAttribute)) != null) { continue; // Do not sync this type of object!!!! } keys.Add(att.Name); values.Add(serializeObject(data)); } p.Keys = keys.ToArray(); p.Values = values.ToArray(); return(p); }
/// <summary> /// Returns false when not everything can be deserialized /// </summary> /// <param name="targetType"></param> /// <param name="p"></param> /// <param name="values"></param> /// <returns></returns> private bool deserializeValues(Type targetType, ChangePacket p, out object[] ret) { ret = new object[p.Keys.Length]; for (int i = 0; i < p.Keys.Length; i++) { var key = p.Keys[i]; var value = p.Values[i]; var att = ReflectionHelper.GetAttributeByName(targetType, key); if (!deserializeObject(value, att.Type, out ret[i])) { return(false); } } return(true); }
private void sendLocalChanges() { int length; Data.ModelContainer.ObjectChange[] array; TW.Data.GetObjectChanges(out array, out length); // Buffers for (int i = 0; i < length; i++) { var change = array[i]; if (change.Change == ModelChange.None) { continue; } if (Attribute.GetCustomAttribute(change.ModelObject.GetType(), typeof(NoSyncAttribute)) != null) { continue; // don't sync this type of object } // Create a change packet ChangePacket p = createChangePacket(change.ModelObject, change.Change); // Send!! foreach (var cl in clients) { // Send to each previously synced client these delta updates transporter.SendTo(cl, p); } } }
/// <summary> /// Returns true when the changed was applied successfully /// </summary> /// <param name="p"></param> /// <returns></returns> private bool applyChangePacket(ChangePacket p) { // First decode the serialized objects, and see if there is an unresolved IModelObject amongst them IModelObject target; object[] deserialized; switch (p.Change) { case ModelChange.Added: var type = TW.Data.TypeSerializer.Deserialize(p.TypeFullName); if (!deserializeValues(type, p, out deserialized)) { return(false); } target = (IModelObject)Activator.CreateInstance(type); setObjectGuid(target, p.Guid); if (target.Container == null) { throw new InvalidOperationException("Modelobject did not add itself to a container!! => " + p.TypeFullName); } applyValues(target, p.Keys, deserialized); // Set initial data break; case ModelChange.Modified: target = getObjectByGuid(p.Guid); if (!deserializeValues(target.GetType(), p, out deserialized)) { return(false); } applyValues(target, p.Keys, deserialized); // Apply changes break; case ModelChange.Removed: target = getObjectByGuid(p.Guid); TW.Data.RemoveObject(target); return(true); case ModelChange.None: // do nothing! This should be a dummy packet to notify us of a remote's existance return(true); default: throw new InvalidOperationException(); } return(true); }