예제 #1
0
 public void ReadStructureStampIfNeeded(ObjectReader reader, VersionToleranceLevel versionToleranceLevel, bool forceStampVerification = false)
 {
     if (StampHelpers.IsStampNeeded(this, reader.TreatCollectionAsUserObject))
     {
         ReadStructureStamp(reader, versionToleranceLevel, forceStampVerification);
     }
 }
예제 #2
0
 public void WriteStructureStampIfNeeded(ObjectWriter writer)
 {
     if (StampHelpers.IsStampNeeded(this, writer.TreatCollectionAsUserObject))
     {
         WriteStructureStamp(writer);
     }
 }
예제 #3
0
 public void ReadStructureStampIfNeeded(ObjectReader reader, VersionToleranceLevel versionToleranceLevel)
 {
     if (StampHelpers.IsStampNeeded(this, reader.TreatCollectionAsUserObject))
     {
         ReadStructureStamp(reader, versionToleranceLevel);
     }
 }
예제 #4
0
        public void Stamp(Type type)
        {
            if (!StampHelpers.IsStampNeeded(type, treatCollectionAsUserObject))
            {
                return;
            }
            if (alreadyWritten.Contains(type))
            {
                return;
            }
            alreadyWritten.Add(type);

            var ts = new TypeStamp(type);

            ts.WriteTo(writer);
        }
예제 #5
0
        public void ReadStamp(Type type, bool treatCollectionAsUserObject)
        {
            if (!StampHelpers.IsStampNeeded(type, treatCollectionAsUserObject))
            {
                return;
            }
            if (stampCache.ContainsKey(type))
            {
                return;
            }

            var streamTypeStamp = new TypeStamp();

            streamTypeStamp.ReadFrom(reader);

            if (streamTypeStamp.ModuleGUID == type.Module.ModuleVersionId)
            {
                stampCache.Add(type, StampHelpers.GetFieldsInSerializationOrder(type, true).Select(x => new FieldInfoOrEntryToOmit(x)).ToList());
                return;
            }
            if (versionToleranceLevel == VersionToleranceLevel.Guid)
            {
                throw new InvalidOperationException(string.Format("The class was serialized with different module version id {0}, current one is {1}.",
                                                                  streamTypeStamp.ModuleGUID, type.Module.ModuleVersionId));
            }

            var result            = new List <FieldInfoOrEntryToOmit>();
            var assemblyTypeStamp = new TypeStamp(type, true);

            if (assemblyTypeStamp.Classes.Count != streamTypeStamp.Classes.Count && !versionToleranceLevel.HasFlag(VersionToleranceLevel.InheritanceChainChange))
            {
                throw new InvalidOperationException(string.Format("Class hierarchy changed. Expected {0} classes in a chain, but found {1}.", assemblyTypeStamp.Classes.Count, streamTypeStamp.Classes.Count));
            }

            var cmpResult = assemblyTypeStamp.CompareWith(streamTypeStamp);

            if (cmpResult.ClassesRenamed.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.TypeNameChanged))
            {
                if (versionToleranceLevel.HasFlag(VersionToleranceLevel.AssemblyVersionChanged))
                {
                    foreach (var renamed in cmpResult.ClassesRenamed)
                    {
                        var beforeStrippedVersion = Regex.Replace(renamed.Item1, "Version=[0-9.]*", string.Empty);
                        var afterStrippedVersion  = Regex.Replace(renamed.Item2, "Version=[0-9.]*", string.Empty);

                        if (beforeStrippedVersion != afterStrippedVersion)
                        {
                            throw new InvalidOperationException(string.Format("Class name changed from {0} to {1}", cmpResult.ClassesRenamed[0].Item1, cmpResult.ClassesRenamed[0].Item2));
                        }
                    }
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Class name changed from {0} to {1}", cmpResult.ClassesRenamed[0].Item1, cmpResult.ClassesRenamed[0].Item2));
                }
            }
            if (cmpResult.FieldsAdded.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.FieldAddition))
            {
                throw new InvalidOperationException(string.Format("Field added: {0}.", cmpResult.FieldsAdded[0].Name));
            }
            if (cmpResult.FieldsRemoved.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.FieldRemoval))
            {
                throw new InvalidOperationException(string.Format("Field removed: {0}.", cmpResult.FieldsRemoved[0].Name));
            }
            if (cmpResult.FieldsMoved.Any() && !versionToleranceLevel.HasFlag(VersionToleranceLevel.FieldMove))
            {
                throw new InvalidOperationException(string.Format("Field moved: {0}.", cmpResult.FieldsMoved.ElementAt(0).Key.Name));
            }

            foreach (var field in streamTypeStamp.GetFieldsInAlphabeticalOrder())
            {
                if (cmpResult.FieldsRemoved.Contains(field))
                {
                    result.Add(new FieldInfoOrEntryToOmit(Type.GetType(field.TypeAQN)));
                }
                else if (cmpResult.FieldsMoved.ContainsKey(field))
                {
                    var moved = cmpResult.FieldsMoved[field];
                    var finfo = Type.GetType(moved.OwningTypeAQN).GetField(moved.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                    result.Add(new FieldInfoOrEntryToOmit(finfo));
                }
                else
                {
                    var finfo = Type.GetType(field.OwningTypeAQN).GetField(field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                    result.Add(new FieldInfoOrEntryToOmit(finfo));
                }
            }

            foreach (var field in assemblyTypeStamp.GetFieldsInAlphabeticalOrder().Where(x => x.IsConstructor))
            {
                var finfo = Type.GetType(field.OwningTypeAQN).GetField(field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                result.Add(new FieldInfoOrEntryToOmit(finfo));
            }

            stampCache.Add(type, result);
        }