• 唯一元素List UniqueList


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection.Emit;
    using NUnit.Framework;

    namespace SASTest
    {

        
    #region 唯一列表
        
    //添加元素保证唯一
        
    //修改元素保证唯一
        public class UniqueList<T> : IList<T>
            
    where T : UniqueList<T>.UniqueItem
        {
            List
    <T> list = new List<T>();

            
    public int Count
            {
                
    get
                {
                    
    return list.Count;
                }
            }

            
    public int Add(T item)
            {
                
    if (!Contains(item, false))
                {
                    list.Add(item);
                    item.CheckerEvent 
    += new CallUniqueCheck(Item_CheckerEvent);
                }
                
    else
                {
                    
    throw new NotUniqueException();
                }
                
    return list.Count - 1;
            }

            
    public T this[int index]
            {
                
    get
                {
                    
    return list[index];
                }
                
    set
                {
                    
    if (value == null)
                        
    throw new NullReferenceException();

                    T tmp 
    = list[index];//备份原来的对象
                    list[index] = value;//修改集合中的元素

                    
    if (Contains(value, true))//修改结束判断是否有重复
                    {
                        list[index] 
    = tmp;//如果有重复,恢复集合
                        throw new NotUniqueException();//抛出异常
                    }

                    
    if (!object.ReferenceEquals(tmp, value))//如果没有重复并且替换后的元素和原来的元素不是同一个对象,要为该元素添加属性修改检查事件
                        value.CheckerEvent += new CallUniqueCheck(Item_CheckerEvent);

                }
            }

            
    private void Item_CheckerEvent(T item, Action<T> action)
            {
                T tmp 
    = (T)Activator.CreateInstance(typeof(T));
                Copy(item, tmp);
    //备份原来的属性值到临时对象上
                action(item);
                
    if (Contains(item, true))
                {
                    Copy(tmp, item);
    //如果失败,将备份的信息恢复
                    throw new NotUniqueException();
                }
            }

            
    private bool Contains(T item, bool edit)//检查修改后的集合是否有重复 , 对于添加元素,在添加前检查是否已经有一个同样的。如果是修改, 则先修改再看修改后是否有两个相同的元素。
            {                                       //修改后检查,如果发现有重复,一定要恢复原来的集合
                bool result = false;
                
    if (item == null)
                    
    throw new NullReferenceException();

                
    int count = 0;
                
    foreach (T ui in list)
                {
                    
    if (ui.Equals(item))
                    {
                        count
    ++;
                    }
                }
                
    if (count <= 0)
                    result 
    = false;
                
    else if (count > 0)
                {
                    result 
    = true;
                    
    if (edit && count == 1)
                        result 
    = false;

                }
                
    return result;
            }

            
    private static void Copy(T source, T target)//辅助方法,拷备属性
            {
                Type t 
    = typeof(T);

                
    foreach (var item in t.GetProperties())
                {
                    
    try
                    {
                        item.SetValue(target, item.GetValue(source, 
    null), null);
                    }
                    
    catch (Exception)
                    {
                    }
                }
            }

            
    public delegate void CallUniqueCheck(T item, Action<T> action);

            
    public abstract class UniqueItem
            {
                
    internal event UniqueList<T>.CallUniqueCheck CheckerEvent;

                
    public void TryPropertyChange(Action<T> action)
                {
                    
    if (CheckerEvent != null)
                    {
                        CheckerEvent((T)
    this, action);
                    }
                    
    else//如果是为空表明现在这个对象还没有添加到集合中
                    {
                        action((T)
    this);//直接修改属性
                    }
                }

            }

            
    #region IList<T> 成员

            
    public int IndexOf(T item)
            {
                
    return list.IndexOf(item);
            }

            
    public void Insert(int index, T item)
            {
                
    if (!Contains(item, false))
                {
                    list.Insert(index, item);
                    item.CheckerEvent 
    += new CallUniqueCheck(Item_CheckerEvent);
                }
                
    else
                {
                    
    throw new NotUniqueException();
                }
            }

            
    public void RemoveAt(int index)
            {
                list.RemoveAt(index);
            }

            
    #endregion

            
    #region ICollection<T> 成员

            
    void ICollection<T>.Add(T item)
            {
                
    this.Add(item);
            }

            
    public void Clear()
            {
                
    this.list.Clear();
            }

            
    public bool Contains(T item)
            {
                
    return this.list.Contains(item);
            }

            
    public void CopyTo(T[] array, int arrayIndex)
            {
                
    this.list.CopyTo(array, arrayIndex);
            }

            
    public bool IsReadOnly
            {
                
    get
                {
                    
    return false;
                }
            }

            
    public bool Remove(T item)
            {
                
    return list.Remove(item);
            }

            
    #endregion

            
    #region IEnumerable<T> 成员

            
    public IEnumerator<T> GetEnumerator()
            {
                
    return list.GetEnumerator();
            }

            
    #endregion

            
    #region IEnumerable 成员

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                
    return list.GetEnumerator();
            }

            
    #endregion
        }



        
    public class NotUniqueException : ApplicationException
        {
            
    public NotUniqueException()
                : 
    base("元素重复")
            {

            }
            
    public NotUniqueException(string message)
                : 
    base(message)
            {

            }
        }

        
    #endregion

        
    #region 测试代码
        [TestFixture]
        
    public class Tester
        {
            [Test]
            [ExpectedException(
    "SASTest.NotUniqueException")]
            
    public void AddTest()//添加相同元素 
            {

                UniqueList
    <MyPoint> list = new UniqueList<MyPoint>();

                list.Add(
    new MyPoint { X = 1, Y = 1 });
                list.Add(
    new MyPoint { X = 1, Y = 2 });
                list.Add(
    new MyPoint { X = 2, Y = 1 });
                list.Add(
    new MyPoint { X = 1, Y = 1 });


                Assert.AreEqual(
    3, list.Count);//冲突时添不进相同元素
            }

            [Test]
            [ExpectedException(
    "SASTest.NotUniqueException")]
            
    public void UpdatePropertyTest()//修改元素属性,使元素重复
            {
                UniqueList
    <MyPoint> list = new UniqueList<MyPoint>();
                list.Add(
    new MyPoint { X = 1, Y = 1 });
                list.Add(
    new MyPoint { X = 1, Y = 2 });
                list.Add(
    new MyPoint { X = 2, Y = 1 });

                list[
    0].X = 2;

                Assert.AreEqual(
    1, list[0].X);//冲突时修改不了

                list[
    0].X = 10;
                Assert.AreEqual(
    10, list[0].X);//不冲突时可以修改
            }

            [Test]
            [ExpectedException(
    "SASTest.NotUniqueException")]
            
    public void UpdateTest()//修改集合元素,使元素重复
            {
                UniqueList
    <MyPoint> list = new UniqueList<MyPoint>();
                list.Add(
    new MyPoint { X = 1, Y = 1 });
                list.Add(
    new MyPoint { X = 1, Y = 2 });
                list.Add(
    new MyPoint { X = 2, Y = 1 });

                list[
    0= new MyPoint { X = 1, Y = 2 };

                Assert.AreEqual(
    2, list[0].Y);

                list[
    0= new MyPoint { X = 10, Y = 10 };

                Assert.AreEqual(
    10, list[0].X);
                Assert.AreEqual(
    10, list[0].Y);
            }

        }

        
    public class MyPoint : UniqueList<MyPoint>.UniqueItem
        {
            
    private int _x;

            
    public int X
            {
                
    get { return _x; }
                
    set
                {
                    TryPropertyChange(p 
    => p._x = value);
                }
            }

            
    private int _y;

            
    public int Y
            {
                
    get { return _y; }
                
    set
                {
                    TryPropertyChange(p 
    => p._y = value);
                }
            }

            
    public override bool Equals(object obj)
            {
                
    if (obj == null)
                    
    throw new NullReferenceException();
                MyPoint point 
    = obj as MyPoint;
                
    return this.X.Equals(point.X) && this.Y.Equals(point.Y);
            }
        }

        
    #endregion
    }
  • 相关阅读:
    JSP基础语法
    《进化:从孤胆极客到高效团队》的目录
    什么是Webpack
    程序猿看市场
    mysql多表关联更新
    Nginx+Tomcat配置集群session共享
    DOUBLE精度问题,BigDecimal
    程序员是否该这样
    Spring上传文件报错
    Emoji表情符号录入MySQL数据库报错的解决方案
  • 原文地址:https://www.cnblogs.com/heros/p/1502569.html
Copyright © 2020-2023  润新知