public TupleDescriptor(SerializationInfo info, StreamingContext context) { FieldCount = info.GetInt32("FieldCount"); ValuesLength = info.GetInt32("ValuesLength"); ObjectsLength = info.GetInt32("ObjectsLength"); var typeNames = (string[])info.GetValue("FieldTypes", typeof(string[])); FieldDescriptors = (PackedFieldDescriptor[])info.GetValue("FieldDescriptors", typeof(PackedFieldDescriptor[])); fieldTypes = new Type[typeNames.Length]; for (int i = 0; i < typeNames.Length; i++) { FieldTypes[i] = typeNames[i].GetTypeFromSerializableForm(); } for (int i = 0; i < FieldCount; i++) { PackedFieldAccessorFactory.ProvideAccessor(FieldTypes[i], FieldDescriptors[i]); } }
// Constructors private TupleDescriptor(IList <Type> fieldTypes) { ArgumentValidator.EnsureArgumentNotNull(fieldTypes, "fieldTypes"); FieldCount = fieldTypes.Count; this.fieldTypes = new Type[FieldCount]; FieldDescriptors = new PackedFieldDescriptor[FieldCount]; const int longBits = 64; const int stateBits = 2; const int statesPerLong = longBits / stateBits; var objectIndex = 0; var valueIndex = FieldCount / statesPerLong + Math.Min(1, FieldCount % statesPerLong); var valueBitOffset = 0; var stateIndex = 0; var stateBitOffset = 0; for (int i = 0; i < FieldCount; i++) { var fieldType = fieldTypes[i].StripNullable(); var descriptor = new PackedFieldDescriptor { FieldIndex = i }; PackedFieldAccessorFactory.ProvideAccessor(fieldType, descriptor); FieldTypes[i] = fieldType; FieldDescriptors[i] = descriptor; } var orderedDescriptors = FieldDescriptors .OrderByDescending(d => d.ValueBitCount) .ThenBy(d => d.FieldIndex); foreach (var descriptor in orderedDescriptors) { switch (descriptor.PackingType) { case FieldPackingType.Object: descriptor.ValueIndex = objectIndex++; break; case FieldPackingType.Value: if (descriptor.ValueBitCount > longBits) { if (valueBitOffset > 0) { valueIndex++; valueBitOffset = 0; } descriptor.ValueIndex = valueIndex; descriptor.ValueBitOffset = 0; valueIndex += descriptor.ValueBitCount / longBits + Math.Min(1, descriptor.ValueBitCount % longBits); } else { if (valueBitOffset + descriptor.ValueBitCount > longBits) { valueIndex++; valueBitOffset = 0; } descriptor.ValueIndex = valueIndex; descriptor.ValueBitOffset = valueBitOffset; valueBitOffset += descriptor.ValueBitCount; } break; default: throw new ArgumentOutOfRangeException("descriptor.PackType"); } if (stateBitOffset + stateBits > longBits) { stateIndex++; stateBitOffset = 0; } descriptor.StateIndex = stateIndex; descriptor.StateBitOffset = stateBitOffset; stateBitOffset += stateBits; } ValuesLength = valueIndex + Math.Min(1, valueBitOffset); ObjectsLength = objectIndex; }