public bool Equals(TypeFullDescriptor obj, VersionToleranceLevel versionToleranceLevel)
        {
            if (versionToleranceLevel.HasFlag(VersionToleranceLevel.AllowAssemblyVersionChange))
            {
                return(obj.UnderlyingType.FullName == UnderlyingType.FullName &&
                       obj.TypeModule.Equals(TypeModule, versionToleranceLevel));
            }

            return(Equals(obj));
        }
        public TypeDescriptorCompareResult CompareWith(TypeFullDescriptor previous, VersionToleranceLevel versionToleranceLevel = 0)
        {
            var result = new TypeDescriptorCompareResult();

            var prevFields = previous.fields.ToDictionary(x => x.FullName, x => x);

            foreach (var field in fields.Where(f => !f.IsTransient))
            {
                FieldDescriptor currentField;
                if (!prevFields.TryGetValue(field.FullName, out currentField))
                {
                    // field is missing in the previous version of the class
                    result.FieldsAdded.Add(field);
                    continue;
                }
                // are the types compatible?
                var compareResult = currentField.CompareWith(field, versionToleranceLevel);
                if (compareResult != FieldDescriptor.CompareResult.Match)
                {
                    result.FieldsChanged.Add(field);
                }

                // why do we remove a field from current ones? if some field is still left after our operation, then field addition occured
                // we have to check that, cause it can be illegal from the version tolerance point of view
                prevFields.Remove(field.FullName);
            }

            // result should also contain transient fields, because some of them may
            // be marked with the [Constructor] attribute
            foreach (var nonTransient in prevFields.Values.Where(x => !x.IsTransient))
            {
                result.FieldsRemoved.Add(nonTransient);
            }

            return(result);
        }