using System.Text.Json;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace Elsa.EntityFrameworkCore;
///
/// Compares two objects.
/// Required to make EF Core change tracking work for complex value converted objects.
///
///
/// For objects that implement and ,
/// those implementations will be used for cloning and equality.
/// For plain objects, fall back to deep equality comparison using JSON serialization
/// (safe, but inefficient).
///
public class JsonValueComparer : ValueComparer {
private static string Json(T instance) {
return JsonSerializer.Serialize(instance);
}
private static T DoGetSnapshot(T instance) {
if (instance is ICloneable cloneable)
return (T)cloneable.Clone();
var result = (T)JsonSerializer.Deserialize(Json(instance));
return result;
}
private static int DoGetHashCode(T instance) {
if (instance is IEquatable)
return instance.GetHashCode();
return Json(instance).GetHashCode();
}
private static bool DoEquals(T left, T right) {
if (left is IEquatable equatable)
return equatable.Equals(right);
var result = Json(left).Equals(Json(right));
return result;
}
public JsonValueComparer() : base(
(t1, t2) => DoEquals(t1, t2),
t => DoGetHashCode(t),
t => DoGetSnapshot(t)) {
}
}