using System.Text.Json;
using Microsoft.EntityFrameworkCore.ChangeTracking;
namespace Elsa.Persistence.EFCore;
///
/// 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((t1, t2) => DoEquals(t1!, t2!),
t => DoGetHashCode(t),
t => DoGetSnapshot(t))
{
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();
return JsonSerializer.Deserialize(Json(instance))!;
}
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);
return Json(left).Equals(Json(right));
}
}