public void Compare()

in Lib/Collectors/BaseCompare.cs [117:312]


        public void Compare(IEnumerable<(CollectObject, string)> differentObjects, IEnumerable<(CollectObject, CollectObject)> modifiedObjects, string? firstRunId, string secondRunId)
        {
            differentObjects?.AsParallel().ForAll(different =>
            {
                var colObj = different.Item1;
                var obj = new CompareResult()
                {
                    BaseRunId = firstRunId,
                    CompareRunId = secondRunId,
                };

                if (different.Item2.Equals(firstRunId))
                {
                    obj.Base = colObj;
                    Results[(colObj.ResultType, CHANGE_TYPE.DELETED)].Add(obj);
                }
                else if (different.Item2.Equals(secondRunId))
                {
                    obj.Compare = colObj;
                    Results[(colObj.ResultType, CHANGE_TYPE.CREATED)].Add(obj);
                }
            });

            modifiedObjects?.AsParallel().ForAll(modified =>
            {
                var compareLogic = new CompareLogic();
                compareLogic.Config.IgnoreCollectionOrder = true;
                var first = modified.Item1;
                var second = modified.Item2;

                if (first != null && second != null)
                {
                    var obj = new CompareResult()
                    {
                        Base = first,
                        Compare = second,
                        BaseRunId = firstRunId,
                        CompareRunId = secondRunId
                    };

                    var properties = first.GetType().GetProperties();

                    if (properties is PropertyInfo[])
                    {
                        foreach (var prop in properties)
                        {
                            try
                            {
                                if (Attribute.IsDefined(prop, typeof(SkipCompareAttribute)))
                                {
                                    continue;
                                }
                                List<Diff> diffs;
                                object? added = null;
                                object? removed = null;

                                object? firstProp = prop.GetValue(first);
                                object? secondProp = prop.GetValue(second);
                                if (firstProp == null && secondProp == null)
                                {
                                    continue;
                                }
                                else if (firstProp == null && secondProp != null)
                                {
                                    added = prop.GetValue(second);
                                    diffs = GetDiffs(prop, added, null);
                                }
                                else if (secondProp == null && firstProp != null)
                                {
                                    removed = prop.GetValue(first);
                                    diffs = GetDiffs(prop, null, removed);
                                }
                                else
                                {
                                    var firstVal = prop.GetValue(first);
                                    var secondVal = prop.GetValue(second);

                                    if (firstVal is List<string> && secondVal is List<string>)
                                    {
                                        added = ((List<string>)secondVal).Except((List<string>)firstVal);
                                        removed = ((List<string>)firstVal).Except((List<string>)secondVal);
                                        if (!((IEnumerable<string>)added).Any())
                                        {
                                            added = null;
                                        }
                                        if (!((IEnumerable<string>)removed).Any())
                                        {
                                            removed = null;
                                        }
                                    }
                                    else if (firstVal is List<KeyValuePair<string, string>> && secondVal is List<KeyValuePair<string, string>>)
                                    {
                                        added = ((List<KeyValuePair<string, string>>)secondVal).Except((List<KeyValuePair<string, string>>)firstVal);
                                        removed = ((List<KeyValuePair<string, string>>)firstVal).Except((List<KeyValuePair<string, string>>)secondVal);
                                        if (!((IEnumerable<KeyValuePair<string, string>>)added).Any())
                                        {
                                            added = null;
                                        }
                                        if (!((IEnumerable<KeyValuePair<string, string>>)removed).Any())
                                        {
                                            removed = null;
                                        }
                                    }
                                    else if (firstVal is Dictionary<string, string> && secondVal is Dictionary<string, string>)
                                    {
                                        added = ((Dictionary<string, string>)secondVal)
                                            .Except((Dictionary<string, string>)firstVal)
                                            .ToDictionary(x => x.Key, x => x.Value);

                                        removed = ((Dictionary<string, string>)firstVal)
                                            .Except((Dictionary<string, string>)secondVal)
                                            .ToDictionary(x => x.Key, x => x.Value);
                                        if (!((IEnumerable<KeyValuePair<string, string>>)added).Any())
                                        {
                                            added = null;
                                        }
                                        if (!((IEnumerable<KeyValuePair<string, string>>)removed).Any())
                                        {
                                            removed = null;
                                        }
                                    }
                                    else if (firstVal is Dictionary<string, List<string>> firstDictionary && secondVal is Dictionary<string, List<string>> secondDictionary)
                                    {
                                        added = secondDictionary
                                            .Except(firstDictionary)
                                            .ToDictionary(x => x.Key, x => x.Value);

                                        removed = firstDictionary
                                            .Except(secondDictionary)
                                            .ToDictionary(x => x.Key, x => x.Value);
                                        if (!((Dictionary<string, List<string>>)added).Any())
                                        {
                                            added = null;
                                        }
                                        if (!((Dictionary<string, List<string>>)removed).Any())
                                        {
                                            removed = null;
                                        }
                                    }
                                    else if (firstVal is Dictionary<(TpmAlgId, uint), byte[]> firstTpmAlgDict && secondVal is Dictionary<(TpmAlgId, uint), byte[]> secondTpmAlgDict)
                                    {
                                        added = secondTpmAlgDict.Where(x => !firstTpmAlgDict.ContainsKey(x.Key) || !firstTpmAlgDict[x.Key].SequenceEqual(x.Value));
                                        removed = firstTpmAlgDict.Where(x => !secondTpmAlgDict.ContainsKey(x.Key) || !secondTpmAlgDict[x.Key].SequenceEqual(x.Value));

                                        if (!((IEnumerable<KeyValuePair<(TpmAlgId, uint), byte[]>>)added).Any())
                                        {
                                            added = null;
                                        }
                                        if (!((IEnumerable<KeyValuePair<(TpmAlgId, uint), byte[]>>)removed).Any())
                                        {
                                            removed = null;
                                        }
                                    }
                                    else if ((firstVal is string || firstVal is int || firstVal is bool) && (secondVal is string || secondVal is int || secondVal is bool))
                                    {
                                        if (!compareLogic.Compare(firstVal, secondVal).AreEqual)
                                        {
                                            obj.Diffs.Add(new Diff(prop.Name, firstVal, secondVal));
                                        }
                                    }
                                    else if (firstProp != null && secondProp != null && compareLogic.Compare(firstVal, secondVal).AreEqual)
                                    {
                                        continue;
                                    }
                                    else
                                    {
                                        obj.Diffs.Add(new Diff(prop.Name, firstVal, secondVal));
                                    }

                                    diffs = GetDiffs(prop, added, removed);
                                }
                                foreach (var diff in diffs)
                                {
                                    obj.Diffs.Add(diff);
                                }
                            }
                            catch (InvalidCastException e)
                            {
                                Log.Debug(e, $"Failed to cast {JsonConvert.SerializeObject(prop)}");
                            }
                            catch (Exception e)
                            {
                                Log.Debug(e, "Generic exception. Tell a programmer.");
                            }
                        }
                    }

                    Results[(first.ResultType, CHANGE_TYPE.MODIFIED)].Add(obj);
                }
            });

            foreach (var empty in Results.Where(x => x.Value.Count == 0))
            {
                Results.Remove(empty.Key, out _);
            }
        }