using System; using System.Collections.Generic; using System.Globalization; using System.Security.Cryptography; using System.Text; namespace SyncEngine.Sync { public static class ChangeDetector { public static string ComputeRowHash(IEnumerable values) { var sb = new StringBuilder(); foreach (var value in values) { sb.Append(Normalize(value)); sb.Append('|'); } using (var sha = SHA256.Create()) { var bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString())); var hex = new StringBuilder(bytes.Length * 2); foreach (var b in bytes) { hex.Append(b.ToString("x2")); } return hex.ToString(); } } public static string Normalize(object value) { if (value == null || value == DBNull.Value) { return string.Empty; } if (value is DateTime dt) { return dt.ToUniversalTime().ToString("O"); } if (value is bool b) { return b ? "1" : "0"; } if (value is byte[] bytes) { return Convert.ToBase64String(bytes); } if (value is IFormattable formattable) { return formattable.ToString(null, CultureInfo.InvariantCulture).Trim(); } return Convert.ToString(value, CultureInfo.InvariantCulture).Trim(); } } }