反思:如何获得IEnumerable属性的差异?

时间:2018-02-14 07:23:07

标签: c# reflection ienumerable

我有一个方法可以区分两个相同类型的对象。差异的方法存储在新的动态对象中。如何找到IEnumerable的属性之间的区别?

方法代码:

public class TestDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Login { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public Guid PassportId { get; set; }
    public bool IsDeleted { get; set; }
    public bool IsNotFinded { get; set; }
    public bool IsInvited { get; set; }
    public bool IsAuctionIsCancelled { get; set; }
    public bool IsInvitationRequired { get; set; }
    public string Role { get; set; }
    public bool HasRetailerAccess { get; set; }
    public bool HasExtendedPaidAccess { get; set; }
    public bool HasRatesInPaidMode { get; set; }
    public string PersonalAdminName { get; set; }
    public int? PersonalAdminId { get; set; }
    public bool IsPremoderationAccepted { get; set; }
    public List<int> l { get; set; }

    public TestDto()
    {
        Id = 0;
        Name = "Test Name";
        Login = "Test Login";
        Password = "12345";
        Email = "test@mail.ru";
        PassportId = new Guid();
        IsDeleted = false;
        IsNotFinded = false;
        IsInvited = false;
        IsAuctionIsCancelled = false;
        IsInvitationRequired = false;
        HasRetailerAccess = false;
        HasExtendedPaidAccess = false;
        HasExtendedPaidAccess = false;
        HasRatesInPaidMode = false;
        IsPremoderationAccepted = false;
        l = new List <int> {5, 10, 15, 100};
    }
}


class Program
{
    static object DifferenceOfObjects(object objectNew, object objectOld)
    {
        dynamic expando = new ExpandoObject();
        var expandoDictionary = expando as IDictionary<String, object>;

        if (objectNew.GetType() != objectOld.GetType())
        {
            return expando;
        }
        var oType = objectOld.GetType();

        foreach (var oProperty in oType.GetProperties())
        {
            var oOldValue = oProperty.GetValue(objectOld, null);
            var oNewValue = oProperty.GetValue(objectNew, null);
            if (oNewValue is IEnumerable && !(oNewValue is string))
            {
                //Type IEnumerable property
                Type itemType = oNewValue.GetType().GetGenericArguments()[0];
                //How equals two IEnumerable property oOldValue and oNewValue...?
            }
            else
            if (!Equals(oOldValue, oNewValue))
            {
                expandoDictionary[oProperty.Name] = new { OldValue = oOldValue, NewValue = oNewValue };
            }
        }

        return expando;
    }

    static void Main(string[] args)
    {
        var oOldRecord = new TestDto();
        var oNewRecord = new TestDto();

        oNewRecord.Name = "Modifined";
        oNewRecord.PersonalAdminId = 100;
        oNewRecord.PassportId = Guid.NewGuid();

        var diffObj = DifferenceOfObjects(oNewRecord, oOldRecord);
        Console.ReadLine();
    }

TestDto - 它是用于比较的测试类。 DifferenceOfObjects - 它是找到对象之间差异的方法。

2 个答案:

答案 0 :(得分:1)

最简单的方法是:

bool areEqual = !list1.Except(list2).Any() && !list2.Except(list1).Any();

list1.Except(list2)检索list1中不在list2中的所有元素。 Any()检查结果列表中是否有元素。

这样,您可以检查其他列表中是否没有元素。请注意,您的通用参数必须覆盖Equals()GetHashCode()

为了获得IEnumerable的通用版本,您可以使用Cast<object>()方法。

为了获得差异,您可以执行以下操作:

            var listAsObj1 = (list1 as IEnumerable).Cast<object>();
            var listAsObj2 = (list2 as IEnumerable).Cast<object>();

            var differences = listAsObj1.Except(listAsObj2)            // In 1 (not in 2)
                                .Concat(listAsObj2.Except(listAsObj1)) // In 2 (not in 1)
                                .Select(_ => _.ToString());            // As string values

答案 1 :(得分:0)

    static object DifferenceOfObjects(object objectNew, object objectOld)
    {
        dynamic expando = new ExpandoObject();
        var expandoDictionary = expando as IDictionary<String, object>;

        if (objectNew.GetType() != objectOld.GetType())
        {
            return expando;
        }
        var oType = objectOld.GetType();

        foreach (var oProperty in oType.GetProperties())
        {
            var oOldValue = oProperty.GetValue(objectOld, null);
            var oNewValue = oProperty.GetValue(objectNew, null);

            if (Equals(oOldValue, oNewValue))
            {
                continue;
            }

            if (oNewValue is IEnumerable && oOldValue is IEnumerable)
            {
                var enumerableNew = (oNewValue as IEnumerable).Cast<object>();
                var enumerableOld = (oOldValue as IEnumerable).Cast<object>();

                if (enumerableOld.SequenceEqual(enumerableNew))
                {
                    continue;
                }
            }

            expandoDictionary[oProperty.Name] = new { OldValue = oOldValue, NewValue = oNewValue };
        }

        return expando;
    }