Using C#, is there any way I can compare and check if an anonymous object is equal to a normal object if both of them have the same properties?
For example:
User normalUser = new() { Id = 1, Email = "[email protected]", LastLogin = DateTime.Now };
var anonymousUser = new { Id = 1, Email = "[email protected]", LastLogin = DateTime.Now };
if (normalUser == anonymousUser) // This comparison gives an error
{
Console.WriteLine("Both are same.");
}
CodePudding user response:
Reflection is the way to go. But there are several implementations out there, one easy to use solution is the CompareNETObjects nuget package:
CompareLogic comparer = new CompareLogic(new ComparisonConfig { IgnoreObjectTypes = true });
if (comparer.Compare(normalUser, anonymousUser).AreEqual)
{
Console.WriteLine("Both are same.");
}
CodePudding user response:
Below is a sample implementation using reflection that satisfies your question. Note that for a more thorough implementation you should probably use a well-established library specialized in this kind of stuff. You may refer to @jeroenh's answer.
using System.Reflection;
DateTime lastLogin = DateTime.Now;
User normalUser = new() { Id = 1, Email = "[email protected]", LastLogin = lastLogin };
var anonymousUser = new { Id = 1, Email = "[email protected]", LastLogin = lastLogin };
if (ReflectionUtils.AreObjectsEqualByProperty(normalUser, anonymousUser))
{
Console.WriteLine("Both are same.");
}
public class User
{
public int Id { get; init; }
public string Email { get; init; }
public DateTime LastLogin { get; init; }
}
public static class ReflectionUtils
{
public static bool AreObjectsEqualByProperty(object? a, object? b)
{
const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public;
if (a is null && b is null)
return true;
if (a is null || b is null)
return false;
Type aType = a.GetType();
Type bType = b.GetType();
PropertyInfo[] aProperties = aType.GetProperties(Flags);
foreach (PropertyInfo aProperty in aProperties)
{
PropertyInfo? bProperty = bType.GetProperty(aProperty.Name, Flags);
// one of a's properties is not present on b
if (bProperty is null)
return false;
object? aValue = aProperty.GetValue(a);
object? bValue = bProperty.GetValue(b);
// property values are different
if (!Equals(aValue, bValue))
return false;
}
// Does b have extra properties that are not present on a?
bool bHasExtraProperties = bType
.GetProperties(Flags)
.Any(bProperty => aProperties.FirstOrDefault(aProperty => aProperty.Name == bProperty.Name) is null);
return !bHasExtraProperties;
}
}
