<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->
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
}
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
}