private static void ValidateSourceEqual(this Attribute[] targetAttributes, Attribute[] sourceAttributes, Tuple<string, string> rootTargetAndSourceFullNames) { Contract.Requires(targetAttributes != null); Contract.Requires(rootTargetAndSourceFullNames != null); Contract.Requires(rootTargetAndSourceFullNames.Item1 != null); Contract.Requires(rootTargetAndSourceFullNames.Item2 != null); Contract.Requires(rootTargetAndSourceFullNames.Item1 != rootTargetAndSourceFullNames.Item2); Assert.That(sourceAttributes != null, "Could not find source attributes"); Assert.That(sourceAttributes != targetAttributes); Assert.That(sourceAttributes.Length == targetAttributes.Length); var sourceAttributeList = sourceAttributes.ToList(); var targetAttributeList = targetAttributes.ToList(); Assert.That(sourceAttributeList.Count == targetAttributeList.Count); if (sourceAttributeList.Count == 0) { return; } var attributeSorter = new Comparison<Attribute>( (left, right) => { var comparison = left.GetType().MetadataToken.CompareTo(right.GetType().MetadataToken); if (comparison != 0 || left.Match(right)) { return comparison; } // same type, and non-matching instances // don't really care what "less than" means, just picking something consistent return string.Compare(left.ToXElement().ToString(), right.ToXElement().ToString(), StringComparison.Ordinal); }); sourceAttributeList.Sort(attributeSorter); targetAttributeList.Sort(attributeSorter); for (var i = 0; i < sourceAttributeList.Count && i < targetAttributeList.Count; i++) { Assert.That(sourceAttributeList[i].Match(targetAttributeList[i])); // this will fail for mixed type arguments } }