//------------------------------------------------------------------------------------- #region << Methods >> /// <summary> /// Возвращает true, если объект заглушен, false - если зарегистрирован /// </summary> /// <param name="obj"></param> /// <param name="cox"></param> /// <param name="typeid"></param> /// <param name="objid"></param> /// <returns></returns> private static bool StubGOLObject(GlobalObject obj, SerContext cox, ushort typeid, uint objid) { if(cox.asEmptyTypes.Contains(obj.GetType()) || cox.asEmptyObjects.Contains(obj)) { #region SerObjectInfo si = new SerObjectInfo(); si.typeID = (ushort)InfraTypes.PulsarEmptyStub; si.objID = objid; si.fields = new List<SerFieldInfo>(1); SerFieldInfo fsi = new SerFieldInfo(); fsi.typeID = typeid; si.fields.Add(fsi); if(obj is GlobalObject) { fsi = new SerFieldInfo(); fsi.typeID = (ushort)PrimitiveTypes.OID; fsi.name = "oid"; fsi.value = ToBytes(((GlobalObject)obj).OID); si.fields.Add(fsi); } si.Save(cox.stream); #endregion return true; } bool noStub = cox.noStubObjects.Contains(obj); if(noStub == false && cox.noStubTypes.Count > 0) { Type t = obj.GetType(); while(t != null) if((noStub = cox.noStubTypes.Contains(t)) == true) break; else t = t.BaseType; } if(typeid == 0) typeid = cox.types.GetTypeID(obj.GetType()); if(objid == 0) objid = cox.objs.GetObjID(typeid, obj); if(noStub) { cox.stream.WriteUInt16((ushort)InfraTypes.GOLObjectRegistrator); if(Pulsar.Server.ServerParamsBase.IsServer == false && GOL.Contains(obj) == false) GOL.Add(obj); } else cox.stream.WriteUInt16((ushort)InfraTypes.GOLObjectStub); cox.stream.WriteUInt16(typeid); cox.stream.WriteUInt32(objid); cox.stream.WriteBytes(ToBytes(obj.OID)); if(noStub) { if(((IReadWriteLockObject)obj).IsLocked == false) ((IReadWriteLockObject)obj).BeginRead(); cox.stack.Push(obj); } return !noStub; }
//------------------------------------------------------------------------------------- /// <summary> /// Сериализует объект в поток. /// </summary> /// <param name="stream">Поток сериализации/</param> /// <param name="obj">Сериализуемый объект.</param> /// <param name="pars">Параметры сериализации.</param> public static void Serialize(Stream stream, object obj, PulsarSerializationParams pars) { try { if(obj == null) return; if(stream == null) throw new ArgumentNullException("stream"); if(stream.CanWrite == false) throw new Exception("Указанный поток сериализации не позволяет запись!"); SerContext cox = new SerContext(stream, pars); Type objType = obj.GetType(); if(IsPrimitive(objType) || objType == typeof(string) || objType == typeof(RefString) || obj is Array || obj is Type || obj is ISelfSerialization) obj = new PulsarPrimitiveHolder(obj); else if(cox.mode != PulsarSerializationMode.Backup && obj is GlobalObject) { if(StubGOLObject((GlobalObject)obj, cox, 0, 0)) // cox.noStubObjects.Contains(obj) == false && { stream.WriteUInt16(ushort.MaxValue); return; } } if(cox.stack.Contains(obj) == false) cox.stack.Push(obj); ushort objTypeID = 0; uint objID = 0; SerObjectInfo si = null; while(cox.stack.Count > 0) { obj = cox.stack.Pop(); objType = obj.GetType(); objTypeID = cox.types.GetTypeID(objType); objID = cox.objs.GetObjID(objTypeID, obj); if(si == null) { si = new SerObjectInfo() { fields = new List<SerFieldInfo>() }; si.fields.Add(new SerFieldInfo() { name = "$root$" }); if(obj is GlobalObject) { SerFieldInfo fsi = new SerFieldInfo(); fsi.typeID = (ushort)PrimitiveTypes.OID; fsi.name = "oid"; fsi.value = ToBytes(((GlobalObject)obj).OID); si.fields.Add(fsi); } } else si = new SerObjectInfo(); if(cox.asEmptyTypes.Contains(objType) || cox.asEmptyObjects.Contains(obj)) { #region si.typeID = (ushort)InfraTypes.PulsarEmptyStub; si.objID = objID; if(si.fields == null) si.fields = new List<SerFieldInfo>(1); SerFieldInfo fsi = new SerFieldInfo(); fsi.typeID = objTypeID; si.fields.Add(fsi); if(obj is GlobalObject) { fsi = new SerFieldInfo(); fsi.typeID = (ushort)PrimitiveTypes.OID; fsi.name = "oid"; fsi.value = ToBytes(((GlobalObject)obj).OID); si.fields.Add(fsi); } si.Save(stream); #endregion continue; } si.typeID = objTypeID; si.objID = objID; CallOnSerializing(obj, cox); if(obj is ISerializable) { #region SerializationInfo serInfo = new SerializationInfo(objType, nativeConverter); ((ISerializable)obj).GetObjectData(serInfo, new StreamingContext()); FieldWrap m_members = null; FieldWrap m_data = null; TypeSerializationWrap tw = TypeSerializationWrap.GetTypeSerializationWrap(typeof(SerializationInfo)); foreach(FieldWrap fw in tw.Fields) if(fw.Name == "m_members") m_members = fw; else if(fw.Name == "m_data") m_data = fw; if(si.fields == null) si.fields = new List<SerFieldInfo>(2); SerFieldInfo fsi = new SerFieldInfo(); fsi.typeID = (ushort)InfraTypes.StringArr; fsi.name = "m_members"; fsi.value = PackArray((Array)m_members.Get(serInfo), cox); si.fields.Add(fsi); fsi = new SerFieldInfo(); fsi.typeID = (ushort)InfraTypes.ObjectArr; fsi.name = "m_data"; fsi.value = PackArray((Array)m_data.Get(serInfo), cox); si.fields.Add(fsi); si.Save(stream); CallOnSerialized(obj, cox); #endregion continue; } string pref = ""; while(objType != typeof(object)) { //foreach(FieldInfo fi in objType.GetFields(fieldsDiscovery)) foreach(FieldWrap fw in TypeSerializationWrap.GetTypeSerializationWrap(objType).Fields) { if(fw.NoSerMode != null) if(fw.NoSerMode.Value == PulsarSerializationMode.Default || cox.mode == PulsarSerializationMode.Default || (fw.NoSerMode & cox.mode) > 0) continue; object val = fw.Get(obj); if(val == null || val is Delegate) continue; Type valType = val is Type ? typeof(Type) : val.GetType(); if(valType.IsValueType && valType == fw.Type && val.Equals(Activator.CreateInstance(valType))) continue; if(fw.ByDemandModes != null) if(fw.ByDemandModes.Value == PulsarSerializationMode.Default || cox.mode == PulsarSerializationMode.Default || (fw.ByDemandModes & cox.mode) == 0) { if(cox.opts.HasFlag(PulsarSerializationOptions.IgnoreAllByDemandSerialization) == false && cox.byDemandTypes.Contains(valType) == false) continue; } SerFieldInfo fsi = new SerFieldInfo(); fsi.typeID = cox.types.GetTypeID(valType); fsi.name = pref + fw.Name; // При добавлении, посмотреть PackArray if(fsi.typeID <= 25 || valType.IsEnum || fsi.typeID == (uint)InfraTypes.RefString) fsi.value = ToBytes(val); else if(val is ISelfSerialization) { CallOnSerializing(val, cox); fsi.value = ((ISelfSerialization)val).GetSerializedData(); CallOnSerialized(val, cox); } else if(val is Type) fsi.value = ToBytes(cox.types.GetTypeID((Type)val)); else if(val is Array) fsi.value = PackArray((Array)val, cox); else { uint id; if(cox.objs.AddAsNew(fsi.typeID, val, out id)) if(val is GlobalObject && pars != null && pars.Options.HasFlag(PulsarSerializationOptions.DeepSerialization) == false) StubGOLObject((GlobalObject)val, cox, fsi.typeID, id); else cox.stack.Push(val); fsi.value = ToBytes(id); } if(si.fields == null) si.fields = new List<SerFieldInfo>(); si.fields.Add(fsi); } objType = objType.BaseType; if(objType == null || objType == typeof(object)) break; pref += '.'; } si.Save(stream); CallOnSerialized(obj, cox); } stream.WriteUInt16(ushort.MaxValue); } catch { throw; } }
//------------------------------------------------------------------------------------- public void Load(Stream fs) { // typeID - уже должен быть прочитан try { objID = fs.ReadUInt32(); byte count = (byte)fs.ReadByte(); if(count > 0) index = new Dictionary<string, SerFieldInfo>(count); for(; count > 0; count--) { SerFieldInfo sfi = new SerFieldInfo(); sfi.Load(fs); index.Add(sfi.name, sfi); } } catch { throw; } }