public void WriteDefinition(IFieldWriter writer) { writer.Write(m_IsCachable); int nestingDepth = GetNestingDepth(); writer.Write(nestingDepth); writer.Write(m_DynamicTypeName); WriteDefinitionForThisLevel(writer); }
public void Write(TextWriter writer, Type type) { WriteTypeKind(writer, type); writer.Write(" \""); _typeNameWriter.Write(writer, type); writer.Write("\" as "); _escapedTypeNameWriter.Write(writer, type); writer.WriteLine(" {"); WriteMembers( writer, () => _queryType.GetFields(type), i => _fieldWriter.Write(writer, i)); WriteMembers( writer, () => _queryType.GetProperties(type), i => _propertyWriter.Write(writer, i)); WriteMembers( writer, () => _queryType.GetMethods(type), i => _methodWriter.Write(writer, i)); WriteMembers( writer, () => _queryType.GetEvents(type), i => _eventWriter.Write(writer, i)); writer.WriteLine("}"); }
/// <summary> /// Helper method to write out a single run (either repating or unique values) /// </summary> private void WriteRun(T[] array, IFieldWriter writer, ref int runLength, ref int currentIndex, ref int peekIndex) { // This handles the edge case of the last run containing only one value if (currentIndex == array.Length - 1) { runLength = -1; } // Write the length of the run first writer.Write(runLength); // is this a repeating run? if (runLength > 0) { // for a repeating run, write the value once but advance the index by runLength WriteValue(writer, array[currentIndex]); currentIndex += runLength; } else { // for a unique run, write each value while (runLength < 0) { WriteValue(writer, array[currentIndex++]); runLength++; } } // Having written this run, get ready for the next one peekIndex = currentIndex + 1; runLength = 0; }
/// <summary> /// Request the packet object write out all of its fields. /// </summary> /// <param name="packet"></param> /// <param name="writer"></param> internal void WriteFields(IPacket packet, IFieldWriter writer) { if (packet is GenericPacket) { //TODO: Update generic packet handling //packet.WriteFields(writer); } else { //We need all of our base classes to write out before us if (m_BasePacket != null) { m_BasePacket.WriteFields(packet, writer); } //and finally write out our information, if we have any. if (m_WriteMethod != null && m_Fields.Count > 0) { //we need to create a serialized packet for this new level so the write method can store information SerializedPacket serializedPacket = new SerializedPacket(this); m_WriteMethod.Invoke(packet, new object[] { this, serializedPacket }); //and now write out the fields to serialization. for (int curFieldIndex = 0; curFieldIndex < Fields.Count; curFieldIndex++) { FieldDefinition fieldDefinition = Fields[curFieldIndex]; writer.Write(serializedPacket.Values[curFieldIndex], fieldDefinition.FieldType); } } } }
public void Write(TextWriter writer, Type type, IQueryType queryType) { WriteTypeKind(writer, type); writer.Write(' '); _typeNameWriter.Write(writer, type); if (type.BaseType != null) { writer.Write(" : "); _typeNameWriter.Write(writer, type.BaseType); } var implementedInterfaces = queryType.GetInterfaces(type).ToArray(); if (implementedInterfaces.Length > 0) { writer.Write(" implements "); writer.Write(string.Join(',', implementedInterfaces.Select(_typeNameConverter.ToString))); } writer.WriteLine(" {"); WriteMembers("Fields", writer, () => queryType.GetFields(type), i => _fieldWriter.Write(writer, i)); WriteMembers("Properties", writer, () => queryType.GetProperties(type), i => _propertyWriter.Write(writer, i)); WriteMembers("Methods", writer, () => queryType.GetMethods(type), i => _methodWriter.Write(writer, i)); WriteMembers("Events", writer, () => queryType.GetEvents(type), i => _eventWriter.Write(writer, i)); writer.WriteLine("}"); }
private void WriteDefinitionForThisLevel(IFieldWriter writer) { if (m_BasePacket != null) { m_BasePacket.WriteDefinitionForThisLevel(writer); } writer.Write(m_TypeName); writer.Write(m_Version); writer.Write(m_Fields.Count); foreach (FieldDefinition fieldDefinition in m_Fields) { writer.Write(fieldDefinition.Name); writer.Write((int)fieldDefinition.FieldType); } // Writer out any associated sub-packets writer.Write(m_SubPackets.Count); for (int i = 0; i < m_SubPackets.Count; i++) { m_SubPackets[i].WriteDefinition(writer); } }
/// <summary> /// Writes an array of type T to the stream. /// </summary> /// <param name="array">Data to be written</param> /// <param name="writer">Stream to write the data into</param> public void Write(T[] array, IFieldWriter writer) { writer.Write((UInt32)array.Length); int currentIndex = 0; int peekIndex = currentIndex + 1; int runLength = 0; // iterate across the array writing out a series of "runs" in which each // run is either a repetition of the same value or a sequence of unique values. while (currentIndex < array.Length) { // check for the end of the array if (peekIndex < array.Length) { // is this the start of a new run? if (runLength == 0) { // is this a run or repeated values? if (AreEqual(array[peekIndex], array[peekIndex - 1])) { // since the first two values match, we know we have a run of at least 2 repeating values runLength = 2; } else { // if the first two values differ, we have a run of at least 1 unique value runLength = -1; } peekIndex += 1; } else if (runLength > 0) { // is the run of repeating values continuing? if (AreEqual(array[peekIndex], array[peekIndex - 1])) { runLength += 1; peekIndex += 1; } else { WriteRun(array, writer, ref runLength, ref currentIndex, ref peekIndex); } } else // runLength < 0 { // is the run of unique values continuing? if (!AreEqual(array[peekIndex], array[peekIndex - 1])) { runLength -= 1; // we decrement because we're accumulating a negative length peekIndex += 1; } else { // don't include the last value because it is part of the next (repeating) run WriteRun(array, writer, ref runLength, ref currentIndex, ref peekIndex); } } } else { WriteRun(array, writer, ref runLength, ref currentIndex, ref peekIndex); } } }
/// <summary> /// Write the data needed to serialize the state of the packet /// </summary> /// <param name="packet">Object to be serialized, must implement IPacket</param> public void Write(IPacket packet) { //Before we do anything - is this a cached packet that's already been written out? ICachedPacket cachedPacket = packet as ICachedPacket; if (cachedPacket != null) { //it is cacheable - is it in the cache? if (m_PacketCache.Contains(cachedPacket)) { //good to go, we're done. return; } } //First, we need to find out if there are any packets this guy depends on. If there are, //they have to be serialized out first. They may have been - they could be cached. //to do this, we'll need to get the definition. PacketDefinition previewDefinition; int previewTypeIndex = m_CachedTypes.IndexOf(packet); if (previewTypeIndex < 0) { //we're going to get the definition, BUT we're not going to cache it yet. //This is because we recurse on our self if there are required packets, and if one of those //packets is our same type, IT has to write out the definition so that it's on the stream //before the packet itself. previewDefinition = PacketDefinition.CreatePacketDefinition(packet); } else { previewDefinition = m_CachedTypes[previewTypeIndex]; } Dictionary <IPacket, IPacket> requiredPackets = previewDefinition.GetRequiredPackets(packet); foreach (IPacket requiredPacket in requiredPackets.Values) { Write(requiredPacket); //this will handle if it's a cached packet and shouldn't be written out. } //Begin our "transactional" phase try { // This routine is written to either write a complete packet, or to write nothing. // As we build up the packet, we will write to a MemoryStream. Only after we've // built up the complete packet will we write it to the actual stream. m_Buffer.SetLength(0); m_Buffer.Position = 0; // The first time a packet type is written, we send along a packet definition PacketDefinition definition; int typeIndex = m_CachedTypes.IndexOf(packet); if (typeIndex < 0) { // Record that we've seen this type so we don't bother sending the PacketDefinition again definition = PacketDefinition.CreatePacketDefinition(packet); typeIndex = m_CachedTypes.Count; m_CachedTypes.Add(definition); // Each packet always starts with a packet type index. And the first time a new // index is used, it is followed by the packet definition. m_BufferWriter.Write((UInt32)typeIndex); definition.WriteDefinition(m_BufferWriter); } else { // If this type has been written before, just send the type index m_BufferWriter.Write((UInt32)typeIndex); definition = m_CachedTypes[typeIndex]; } // if it's cacheable then we need to add it to our packet cache before we write it out if (definition.IsCachable) { // In the case of an ICachedPacket, we need to add it to the cache. // we'd have already bailed if it was in there. // Note: Use previous cast for efficiency, but we must recast here *if* packet gets reassigned above // Currently it does not get reassigned, so cachedPacket which we cast packet into above is still valid. m_PacketCache.AddOrGet(cachedPacket); } //Finally, and it really is a long journey, we ask the definition to write out //the individual fields for the packet definition.WriteFields(packet, m_BufferWriter); } catch (Exception ex) { GC.KeepAlive(ex); Rollback(); throw; } #if ADD_GUARD_BYTES m_Stream.Write(s_PreambleGuardPattern, 0, s_PreambleGuardPattern.Length); #endif // Write the data to the stream preceded by the length of this packet // NOTE: The logic below is careful to ensure that the length and payload is written in one call // This is necessary to ensure that the GZipStream writes the whole packet in edge cases // of writing the very last packet as an application is exiting. var payloadLength = (int)m_Buffer.Position; // get the actual length of the payload MemoryStream encodedLength = FieldWriter.WriteLength(payloadLength); var lengthLength = (int)encodedLength.Length; var packetBytes = new byte[lengthLength + payloadLength]; encodedLength.Position = 0; // reset the position in preparation to read the data back encodedLength.Read(packetBytes, 0, lengthLength); m_Buffer.Position = 0; // reset the position in preparation to read the data back m_Buffer.Read(packetBytes, lengthLength, payloadLength); m_Stream.Write(packetBytes, 0, packetBytes.Length); #if ADD_GUARD_BYTES m_Stream.Write(s_PostambleGuardPattern, 0, s_PostambleGuardPattern.Length); #endif Commit(); }