简体   繁体   English

C# - 将匿名 object 与具有相同属性的普通 object 进行比较

[英]C# - Compare an anonymous object with a normal object with same properties

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?使用 C#,有什么方法可以比较和检查匿名 object 是否等于普通 object 如果它们都具有相同的属性?

For example:例如:

    User normalUser = new() { Id = 1, Email = "normal@example.com", LastLogin = DateTime.Now };
    var anonymousUser = new { Id = 1, Email = "normal@example.com", LastLogin = DateTime.Now };

    if (normalUser == anonymousUser) // This comparison gives an error
    {
        Console.WriteLine("Both are same.");
    }

Reflection is the way to go.反射是 go 的方式。 But there are several implementations out there, one easy to use solution is the CompareNETObjects nuget package:但是有几种实现,一种易于使用的解决方案是CompareNETObjects nuget package:

CompareLogic comparer = new CompareLogic(new ComparisonConfig { IgnoreObjectTypes = true });

if (comparer.Compare(normalUser, anonymousUser).AreEqual)
{
    Console.WriteLine("Both are same.");
}

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.您可以参考@jeroenh 的回答。

using System.Reflection;

DateTime lastLogin = DateTime.Now;
User normalUser = new() { Id = 1, Email = "normal@example.com", LastLogin = lastLogin };
var anonymousUser = new { Id = 1, Email = "normal@example.com", 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM