我有个public class A
{
    public int AID{get;set;}
    public IList<B> BList{get;set;}
}
public class B
{
    public int BID{get;set;}
    public IList<C> CList{get;set;}
}public class C
{
    public int CID{get;set;}
}static void Main(string[] args)
{
            IList<A> aList = new List<A>();
            aList.Add(new A { AID = 1, BList = new List<B>() { new B{BID=1}} });
            aList.Add(new A { AID = 2, BList = new List<B>() { new B { BID = 2 } } });
            EqualityComparer<A> eq = new EqualityComparer<A>();
            //eq.ComparerString.Add("AID");
            eq.ComparerString.Add("BList");
            bool isExists = aList.Contains(new A { BList = new List<B>() { new B { BID = 1 } } }, eq);
            Console.WriteLine(isExists);
}然后 有个比较类
 public class EqualityComparer<T> :  IEqualityComparer<T>
    {
        /// <summary>
        /// 需要比较的属性名称
        /// </summary>
        public IList<string> ComparerString
        {
            get;
            set;
        }        public EqualityComparer()
        {
            ComparerString = new List<string>();
        }        public bool Equals(T a, T b)
        {
            if (object.ReferenceEquals(a, b))
                return true;
            if (object.ReferenceEquals(a, null) || object.ReferenceEquals(b, null))
                return false;
            
            if (ComparerString == null || ComparerString.Count <= 0)
            {
                bool isSame = false;
                foreach (PropertyInfo p in a.GetType().GetProperties())
                {
                    if (p.PropertyType.IsGenericType)
                    {
                        if (!IsListSame(p.GetValue(a, null), b.GetType().GetProperty(p.Name).GetValue(b, null)))
                            return false;
                    }
                    else
                    {
                        isSame = p.GetValue(a, null) == b.GetType().GetProperty(p.Name).GetValue(b, null);
                        if (!isSame)
                            return false;
                    }
                }
                return true;
            }
            else
            {
                foreach (string str in ComparerString)
                {
                    if (a.GetType().GetProperty(str).PropertyType.IsGenericType)
                    {
                        if (!IsListSame(a.GetType().GetProperty(str).GetValue(a, null), b.GetType().GetProperty(str).GetValue(b, null)))
                            return false;
                    }
                    else
                    {
                        if (a.GetType().GetProperty(str).GetValue(a, null) != b.GetType().GetProperty(str).GetValue(b, null))
                            return false;
                    }
                }
                return true;
            }
        }        private bool IsListSame(object oa,object ob)////这个比较IList 怎么比较 不知道类型 怎么弄?
        {
            IList<object> a=new List<object>();
            IList<object> b = new List<object>();                        foreach (object suba in a)
            {
                if (b.Contains(suba))
                    return true;
            }
            return false;
        }        public int GetHashCode(T o)
        {
            if (object.ReferenceEquals(o, null))
                return 0;
            int hashResult = 0;
            if (ComparerString == null || ComparerString.Count <= 0)
            {
                
                foreach (PropertyInfo p in o.GetType().GetProperties())
                {
                    hashResult = hashResult ^ (p.GetValue(o, null) != null ? p.GetValue(o, null).GetHashCode() : 0);
                }
                return hashResult;
            }
            else
            {
                foreach (string str in ComparerString)
                {
                    hashResult = hashResult ^ (o.GetType().GetProperty(str).GetValue(o, null) != null ? o.GetType().GetProperty(str).GetValue(o, null).GetHashCode() : 0);
                }
                return hashResult;
            }
        }
    }
但是问题就卡在了IList类型的属性怎么比较 反射怎么弄?
不会
求各位大神讲解

解决方案 »

  1.   

    private bool IsListSame(object oa,object ob)////这个比较IList 怎么比较 不知道类型 怎么弄?
            {
                IList<object> a=new List<object>();
                IList<object> b = new List<object>();                        foreach (object suba in a)
                {
                    if (b.Contains(suba))
                        return true;
                }
                return false;
            }
    这个方法和你其他的那些代码没有看出来有什么关系。
    2个参数没看出来有什么用。
      

  2.   

    if (a.GetType().GetProperty(str).PropertyType.IsGenericType)
    不需要考虑b的泛型属性吗?你写个抽象类,它里面重写object.Equals()方法
      

  3.   


    这个方法只是比较IList的方法 oa为一个IList反射的值 ob是要比较的IList反射的值
    还有 我是比较对象下面的IList属性 下面还有子对象 如果只是单纯的IList 可以用Equals()比较
      

  4.   

    还有 请看清楚  我想通过BList这个属性来比较 
    所以用到了反射 
    我就是想写个可以兼容多种类型 情况下的对象比较
      

  5.   

    还有 请看清楚  我想通过BList这个属性来比较 
    所以用到了反射 
    我就是想写个可以兼容多种类型 情况下的对象比较
      

  6.   

    这就是关键代码啊 ,也不长  就是想知道 怎么样利用反射比较对象的IList属性值
      

  7.   

    你的IList的比较真麻烦,嵌套太深,这样效率也很低,建议你使用Struct来代替Class,那样比较的就不会引用地址而是值本身。
        public class EqualityComparer<T> : IEqualityComparer<T> where T : A
        {
            public bool Equals(T x, T y)
            {
                if (x == null)
                {
                    if (y == null)
                        return true;
                    else
                        return false;
                }
                else
                {
                    if (y == null)
                        return false;
                    else
                    {
                        if (x.AID != y.AID)
                            return false;
                        else if (x.BList == null)
                        {
                            if (y.BList == null)
                                return true;
                            else
                                return false;
                        }
                        else
                        {
                            if (y.BList == null)
                                return false;
                            else
                            {
                                if (x.BList.Count != y.BList.Count)
                                    return false;
                                else
                                {
                                    for (int i = x.BList.Count - 1; i >= 0; i--)
                                    {
                                        if (x.BList[i].BID != y.BList[i].BID)
                                            return false;
                                        else if (x.BList[i].CList == null)
                                        {
                                            if (y.BList[i].CList == null)
                                                return true;
                                            else
                                                return false;
                                        }
                                        else
                                        {
                                            if (y.BList[i].CList == null)
                                                return false;
                                            else
                                            {
                                                if (x.BList[i].CList.Count != y.BList[i].CList.Count)
                                                    return false;
                                                else
                                                {
                                                    for (int j = x.BList[i].CList.Count - 1; j >= 0; j--)
                                                    {
                                                        if (x.BList[i].CList[j].CID != y.BList[i].CList[j].CID)
                                                            return false;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return true;
            }        public int GetHashCode(T obj)
            {
                return obj.GetHashCode();
            }
        }
      

  8.   

    谢谢!
    你这样我知道 
    我的目的是利用反射去比较 因为你所比较的对象的不确定性 遇到IList就很麻烦 
    所以问题现在就卡在这里了
    利用反射 比较IList是否相等
      

  9.   

    谢谢!
    你这样我知道  
    我的目的是利用反射去比较 因为你所比较的对象的不确定性 遇到IList就很麻烦  
    所以问题现在就卡在这里了
    利用反射 比较IList是否相等 
      

  10.   

    如果你的IList没有嵌套,我愿意帮你写反射的过程,但是嵌套了反射实在头大,我这里只能给你点建议性的方案。
    获取泛型的参数,通过如下方法可获得:
    _List.GetType().GetGenericArguments()
    如果只有一个泛型参数,这个返回的数组长度就是1,如果不是泛型类型,这个返回的数组长度为0.
    然后比较这个泛型类型是否相等,相等则继续比较泛型的属性值。
    比较IList内部的元素时,先判断是否是IList,如果是,强制类型转换到接口IList,调用接口方法获取长度比较,如果长度相同,然后比较每个Item元素的类型,如果类型相同,再判断是否为结构体,结构体直接比较值,如果是类,比较内部属性。不嵌套想起来就头大了,你再嵌套就更加不敢想了(没那么多时间)。
      

  11.   

    还有一个方法,用JSON序列化后,比较序列化后的字符串是否相等,前提是你设计的类型必须可序列化,私有成员不能参与比较。另外[DataContract]标记别用在IList上面,否则对IList的序列化行为会发生改变。
      

  12.   

    我现在不知道怎么样比较IList的泛型类型和它里面的值
    能给点代码提示一下吗?
    谢谢了!
      

  13.   

    我不是说了吗?如果是IList的对象,只要用索引访问器访问就可以得到内部值了,例如_List[0]将得到里面第一个项的值,它的类型是_List.GetType().GetGenericArguments()[0],当然,如果你的是IList<Object>,那么比较类型意义不大,直接通过这个项的值反射类型比较更好。
      

  14.   

    我是循环a的属性来的啊
    foreach (PropertyInfo p in a.GetType().GetProperties())
    ----------
    a下面的BList
    但是p是属性对象没办法通过索引获得到List里面的值
      

  15.   

            foreach (PropertyInfo p in a.GetType().GetProperties())
            {             
                    var obj = p.GetValue(a, null);
                    if (obj is IList)
                    {
                        //转换为IList比较内部项
                        IList lobj = (IList)obj;
                        for (int i = lobj.Count - 1; i >= 0; i--)
                        {
                            var item = lobj[i];//得到内部项,怎么比较自己写
                        }
                    }
                    else
                    {
                        //常规比较
                    }
      

  16.   

    额,我只能说你在玩一个不应该玩的动作IEqualityComparer<T>本身就是一个场合性的东西,也就是说他本来就应该和上下文关联的东西,而非通用滴玩意,请自己想一下微软为啥要重载出这么一个方法让你自己提供IEqualityComparer<T>,很明显就是微软说我不知道你要干啥,这不是通用标准,我做不出来。请你自己根据上下文实现。所以你企图用一个通用的玩意去包装的思维就和本身微软的思路是冲突滴,要能通用的化,微软何必要重载出这个方法给你呢??
      

  17.   

    在你发这之前
    我正好想到了 把(IList)p.GetValue(a,null)就可以了
    不过还是要说声谢谢
    我只是想用反射解决掉对象的不确定性
    我比较喜欢用反射
    呵呵!
      

  18.   

    还有为什么要这样写的问题
    因为我现在遇到了这样的问题
    有多个类型的对象,要比较对象中的Name属性的值是否存在(如果还有其他的属性要求比较的话)
    所以我用到了IEqualityComparer<T>
    和要比较对象的类型的不确定性和属性的不确定性
    所以才会用到反射去解决问题
    本人还是觉得用反射可以灵活的解决掉问题
    不想写那么多重复的代码
    谢谢大家!
      

  19.   

    IList内部有那么一个属性,名字未知,默认叫“Items”,你可以反射后遍历看看是否存在这样的属性,该属性是索引器,可以用索引来访问内部元素,如果要反射该属性的值,p.GetValue(a,null)是不行的,第二个参数这时就需要用到了,例如获取第一个项,_List[0],通过反射就是p.GetValue(a,new Object[] {0}),这里的p是索引化属性,那个a则是_List。
      

  20.   

    p.GetValue(a,null)
    这个事可以获得到IList的值 
    但是是个object的值 
    我把它转成IList的就是一个集合了 
    可以通过索引去取得到里面的值
      

  21.   

    p.GetValue(a,null)
    这个事可以获得到IList的值 
    但是是个object的值 
    我把它转成IList的就是一个集合了 
    可以通过索引去取得到里面的值
      

  22.   

    有多个类型的对象,要比较对象中的Name属性的值是否存在(如果还有其他的属性要求比较的话)==============我只能告诉你在你费劲巴拉的搞这个通用解的时候我的要求不是检查name值是否一样。 我告诉你对象A.name和对象B.username 比较或者我要A.firstName+A.lastName和B.Name 比较现在你还觉着你封装这块有通用性吗?ps:别过渡封装,别需求镀金。其实我们大多数人都很想把自己以前的过度封装的类全部砸了,因为他根本就是错误的封装方式
      

  23.   

    一样可以的啊 只不过是需要做下变通而已
    只是简单的比较,我觉得这样子时没有问题的
    如果你要那样写,我只会感觉代码的冗余
    再说我写这个的前提只是在一个IList集合里面判断有没有指定条件重复的对象
    如果你想判断其他的 A类型对象和B类型对象去比较的话 可以去做相应的变通
    没有必要吧相同结构的代码重复写上个七八遍
    没有什么意思
    还有使用反射现在也大多是简单的比较和获取 太复杂的却是消耗性能而不是那么好写的
    做最简单的比较我觉得还是可以使用的
      

  24.   

    public class A
    {
        public int AID{get;set;}
        public IList<B> BList{get;set;}
    }
    public class B
    {
        public int BID{get;set;}
        public IList<C> CList{get;set;}
    }
    加下面这些应该可以了
    public class A1
    {
        public int AID{get;set;}
        public B[] BList{get;set;}
    }
    public class B1
    {
        public int BID{get;set;}
        public [] CList{get;set;}
    }
      

  25.   

    反射,无非就是以Type为中心,运行时操作Type
      

  26.   

    Keep your design simple and clear. Don't confuse yourself later on.
      

  27.   

    如果要比较Name属性的话,你可以强制你下面所有的类从一个带Name的接口继承,比较时强制转化为接口就行了。你所想的正是我前几天所推翻的。我要检测下面反射生成的类是否包含一个事件,如果有,注册,开始用的反射后来怎么看怎么别扭,后来想到了接口,我也觉得,反射是实在没有办法的办法,但凡有办法,就别用反射。丢了强类型的特性了,如果特别喜欢反射,我觉得弱类型语言更适合你。