比较c#中的(特定)对象属性

时间:2015-09-04 22:57:51

标签: c#

this答案为基础,用于比较C#中的对象 Comparing object properties in c#

知道这是一个复杂的主题,我想处理一些更具体的结构。

如果这些代码是简单的值类型,例如此对象,则此代码将匹配属性:

public class BasicStuff
{
    public int anInt { get; set; }
    public bool aBool { get; set; }
}

但是一旦它变得更复杂,这段代码就会失败。

所以我想做的是让它对上面的嵌套对象更有用,例如:

public class NestedStuff
{
    public BasicStuff theBasic { get; set; }
}

以上任何数组,例如:

public class ArrayStuff
{
    public BasicStuff[] theBasicArray { get; set; }
}

最后是上述的任何组合:

public class AllTheStuff
{
    public int anInt { get; set; }
    public bool aBool { get; set; }
    public BasicStuff theBasic { get; set; }
    public BasicStuff[] theBasicArray { get; set; }
}

所以我想出的是以下内容:

    public static bool AllPublicPropertiesEqual<T>(T AObj, T BObj, params string[] ignore) where T : class
    {
        if (AObj != null && BObj != null)
        {
            Type type = typeof(T);
            List<string> ignoreList = new List<string>(ignore);
            foreach (PropertyInfo pInfo in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (!ignoreList.Contains(pInfo.Name))
                {
                    if (pInfo.PropertyType.IsArray)
                    {
                        object AValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
                        object BValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);
                        string t = AValue.GetType().ToString();

                        if (!AllPublicPropertiesEqual<object>(AValue, BValue))
                            return false;
                    }
                    else if (!pInfo.PropertyType.IsValueType && !pInfo.PropertyType.IsPrimitive && !pInfo.PropertyType.IsEnum && pInfo.PropertyType != typeof(string)) 
                    //else if (Convert.GetTypeCode(pInfo.PropertyType) == TypeCode.Object)
                    {
                        object AValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
                        object BValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);

                        if (!AllPublicPropertiesEqual<object>(BValue, AValue))
                            return false;
                    }
                    else
                    {
                        object selfValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
                        object toValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);

                        if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
                            return false;
                    }
                }
            }
            return true;
        }
        return AObj == BObj;
    }

只有这会失败,因为在递归调用AllPublicPropertiesEqual时,我需要传递特定的值类型而不仅仅是通用对象类型。 但我不知道该怎么做......任何想法都非常感谢...

3 个答案:

答案 0 :(得分:0)

您的方法不必是通用的。您可以将方法的开头更改为:

public static bool AllPublicPropertiesEqual(object AObj, object BObj, params string[] ignore) 
{
    if (AObj != null && BObj != null)
    {
        Type type = AObj.GetType();

        if (BObj.GetType() != type)
            throw new Exception("Objects should be of the same type");

        ....
    }

    ....
}

答案 1 :(得分:0)

首先,你应该为这些类创建接口,因为从我看到你可以组合这些类,但所有类都具有相同的属性。第二个选项是使用这些属性创建一些Base抽象类并从中继承。这取决于你选择的是什么。  比在这个Base类或Interface Equals函数中创建,你将直接等于共享属性,它更容易,我觉得更有效: - )

public abstract class BaseStaff {
  public int anInt { get; set; }
  public bool aBool { get; set; }
  public abstract bool Equals(BaseStaff anotherStaff);
}

然后你可以使用这个类在BasicStaff中创建你的BasicStaff类和AllTheStaff类,实现这样的Equals方法。

public override bool Equals(BaseStaff staff) {
   this.anInt == staff.anInt &&
   this.aBool == staff.aBool;
}

在AllTheStaff中你可以像这样覆盖这个方法

public override bool Equals(BaseStaff staff) {
  bool baseEquals = base.Equals(staff);
  bool basicStaffEquals = this.BasicStaff.Equals(staff);
  return baseEquals || basicStaffEquals;    
}

这只是核心理念,也许我不太了解你真正希望实现的目标,但希望它可以帮助你:)

答案 2 :(得分:0)

测试解决方案

        public static bool AllPublicPropertiesEqual<T>(T AObj, T BObj, params string[] ignore) where T : class
    {
        if (AObj != null && BObj != null)
        {
            Type type = typeof(T);
            List<string> ignoreList = new List<string>(ignore);
            foreach (PropertyInfo pInfo in type.GetCType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (!ignoreList.Contains(pInfo.Name))
                {
                    if (pInfo.PropertyType.IsArray)
                    {
                        object aElementValues = (type.GetProperty(pInfo.Name).GetValue(AObj, null));
                        object bElementValues = (type.GetProperty(pInfo.Name).GetValue(BObj, null));

                        if (aElementValues != null && bElementValues != null)
                        {
                            List<object> AListValues = new List<object>();
                            List<object> BListValues = new List<object>();

                            foreach (var v in (IEnumerable)aElementValues)
                                AListValues.Add(v);

                            foreach (var v in (IEnumerable)bElementValues)
                                BListValues.Add(v);

                            if (AListValues.Count == BListValues.Count)
                            {
                                object[] aArray = AListValues.ToArray();
                                object[] bArray = BListValues.ToArray();

                                for (int i = 0; i < aArray.Length; i++)
                                {
                                    if (!AllPublicPropertiesEqual(aArray[i], bArray[i]))
                                        return false;
                                }
                            }
                            else
                                return false;
                        }
                        else if ((aElementValues == null) != (bElementValues == null))
                            return false;
                    }
                    else if (!pInfo.PropertyType.IsValueType && !pInfo.PropertyType.IsPrimitive && !pInfo.PropertyType.IsEnum && pInfo.PropertyType != typeof(string))
                    //else if (Convert.GetTypeCode(pInfo.PropertyType) == TypeCode.Object)
                    {
                        object AObjectValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
                        object BObjectValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);

                        if (!AllPublicPropertiesEqual(BObjectValue, AObjectValue))
                            return false;
                    }
                    else
                    {
                        object aValue = type.GetProperty(pInfo.Name).GetValue(AObj, null);
                        object bValue = type.GetProperty(pInfo.Name).GetValue(BObj, null);

                        if (aValue != bValue && (aValue == null || !aValue.Equals(bValue)))
                            return false;
                    }
                }
            }
            return true;
        }
        return AObj == BObj;
    }
}