回复 寒枫天伤 - PSP 的问题
載體的設計有倆個思路,一個是表格式的,一個是層次的。
????? ms的ADO、DataSet就是表格式的,采用行、列組成的表,然后表集合之間建立聯系。他更貼近關系型數據庫的結構,因此使用簡單、可以充分利用已經成熟的大量研究成果。缺點就是他是抽象的,不直觀。
????? 通常的xml和O/R的設計就是層次的,局部來說也是行(集合)、列(屬性)組成表(對象),區別是表(對象)之間不是平等的關系,而是建立了有點像樹一樣的結構。好處嗎,編寫代碼的時候看著舒服些羅(不是我打擊你),缺點嗎,一沓子了,我最頭大的是數據跟蹤問題。
????? 我無法在一片文章中說明所有的事情,例如序列化、繼承原則、CRUD、數據跟蹤一大堆要處理的事情。
????? 先說說 IBindList和ICancelAddNew接口吧,IBindList是列表綁定的基礎接口,他繼承于IList接口,如果你想綁定到某個表格或者列表中,IList基本上夠了(實際上數組和ICollection也可以),但IBindList提供是否能新增、編輯和刪除的選項,還提供排序、查找等功能(我可沒有實現這個復雜的功能,我使用表格本身的功能),最重要的是他提供了ListChanged事件,這個是你通知外界你的集合發生改變的最好途徑,所以你的集合最好是實現IBindList,而不緊緊是IList。
????? ICancelAddNew接口用在表格的編輯中,你使用表格的時候都知道你新建一行的時候可以按ESC鍵取消新建,實際內部的工作原理是:已經新建了行并添加到行集合,當你按ESC時,刪除掉剛才的一行,所以你必須記住剛才新建的行是第多少行。
(如果沒有記錯的話,.net 1.1是沒有這個接口的 ,.net 2.0才有)????? 下面的代碼是部分的集合代碼(不能運行的),不要以為我能寫多好的程序,其實我是抄System.ComponentModel.Collections.Generic.BindingList<T>的。
Using?directives#region?Using?directives
using?System;
using?System.Collections;
using?System.ComponentModel;
using?Mango.Common.Data;
using?Mango.Common.Properties;
using?System.Reflection;
#endregion
namespace?Mango.Common.Data
{
????/**////?<summary>?行集合對象的基礎類?</summary>
????public?class?DataRowCollectionBase?:?CollectionBase,?IBindingList,?IList,?ICollection,?IEnumerable,?ICancelAddNew
????{
????????//?Fields
????????private?int?addNewPos;
????????private?bool?hookingItems;
????????private?PropertyChangedEventHandler?onItemPropertyChanged;
????????private?bool?allowNew;
????????private?bool?allowEdit;
????????private?bool?allowRemove;
????????private?Type?_itemType;
????????private?object?_parent;
????????//?Events
????????public?event?AddingNewEventHandler?AddingNew;
????????public?event?ListChangedEventHandler?ListChanged;
????????類的初始化方法#region?類的初始化方法
????????/**////?<summary>?創建無父對象的集合?</summary>
????????public?DataRowCollectionBase()
????????{
????????????this.addNewPos?=?-1;
????????????this.allowNew?=?true;
????????????this.allowEdit?=?true;
????????????this.allowRemove?=?true;
????????}
????????/**////?<summary>?創建集合,并為集合設置父對象?</summary>
????????public?DataRowCollectionBase(object?parent)?:this()
????????{
????????????_parent?=?parent;
????????}
????????#endregion
????????AddNew相關方法#region?AddNew相關方法
????????/**////?<summary>
????????///?獲取集合類的名細類型
????????///?</summary>
????????protected?virtual?Type?GetCollectionItemType()
????????{
????????????if?(_itemType?==?null)
????????????{
????????????????Type?collType?=?this.GetType();
????????????????object[]?ps?=?collType.GetCustomAttributes(typeof(DbCollectionAttribute),?true);
????????????????if?(ps?==?null?||?ps.Length?==?0)
????????????????????throw?new?ApplicationException(string.Format(Resources.Error_NotSetDbCollAtt,?collType.Name));
????????????????_itemType?=?((DbCollectionAttribute)ps[0]).TypeContainedInCollection;
????????????}
????????????return?_itemType;
????????}
????????/**////?<summary>?引發?AddingNew?事件?</summary>
????????protected?virtual?void?OnAddingNew(AddingNewEventArgs?e)
????????{
????????????if?(this.AddingNew?!=?null)
????????????{
????????????????this.AddingNew(this,?e);
????????????}
????????}
????????/**////?<summary>?返回新的對象?</summary>
????????private?object?FireAddingNew()
????????{
????????????AddingNewEventArgs?addNewArgs?=?new?AddingNewEventArgs(null);
????????????this.OnAddingNew(addNewArgs);
????????????return?addNewArgs.NewObject;
????????}
????????/**////?<summary>?在向?DataRowCollectionBase?實例中插入新元素之前執行其他自定義進程。?</summary>
????????protected?override?void?OnInsert(int?index,?object?value)
????????{
????????????//檢查新對象的父對象
????????????DataRowBase?row?=?value?as?DataRowBase;
????????????if?(row?!=?null)
????????????{
????????????????if?(row.Parent?!=?null)
????????????????????throw?new?ArgumentException(Resources.Error_ColHaveParent);
????????????}
????????????this.EndNew(this.addNewPos);
????????????this.HookItem(value,?true);
????????????base.OnInsert(index,?value);
????????}
????????/**////?<summary>?在向?DataRowCollectionBase?實例中插入新元素之后執行其他自定義進程。?</summary>
????????protected?override?void?OnInsertComplete(int?index,?object?value)
????????{
????????????//設置新對象的父對象
????????????DataRowBase?row?=?value?as?DataRowBase;
????????????if?(row?!=?null)
????????????????row.SetParent(_parent);
????????????base.OnInsertComplete(index,?value);
????????????this.FireListChanged(ListChangedType.ItemAdded,?index);
????????}
????????/**////?<summary>?將新項添加到列表。</summary>
????????object?IBindingList.AddNew()
????????{
????????????object?newObject?=?this.AddNewCore();
????????????this.addNewPos?=?(newObject?!=?null)???base.List.IndexOf(newObject)?:?-1;
????????????return?newObject;
????????}
????????/**////?<summary>?將新項添加到列表。?</summary>
????????protected?virtual?object?AddNewCore()
????????{
????????????object?newObject?=?this.FireAddingNew();
????????????if?(newObject?==?null)
????????????{
????????????????newObject?=?Activator.CreateInstance(GetCollectionItemType());
????????????????//自動填充關鍵字
????????????????IDataRow?dataRow?=?newObject?as?IDataRow;
????????????????if?(dataRow?!=?null)
????????????????{
????????????????????DataRowType?t?=?dataRow.GetDataRowType();
????????????????????PropertyInfo?pi?=?t.GetPrimaryKeyProperty();
????????????????????pi.SetValue(dataRow,?Guid.NewGuid().ToString("N"),?null);
????????????????}
????????????}
????????????base.List.Add(newObject);
????????????return?newObject;
????????}
????????#endregion
????????ListChanged事件的支持#region?ListChanged事件的支持
????????/**////?<summary>?引發?ListChanged?事件?</summary>
????????protected?virtual?void?OnListChanged(ListChangedEventArgs?e)
????????{
????????????if?(this.ListChanged?!=?null)
????????????{
????????????????this.ListChanged(this,?e);
????????????}
????????}
????????//內部引發ListChanged事件
????????private?void?FireListChanged(ListChangedType?listChangedType,?int?index)
????????{
????????????this.OnListChanged(new?ListChangedEventArgs(listChangedType,?index));
????????}
????????//內部引發ListChanged事件
????????private?void?FireListChanged(ListChangedType?listChangedType,?int?index,string?propertyName)
????????{
????????????PropertyDescriptor?propDesc?=?TypeDescriptor.CreateProperty(GetCollectionItemType(),?propertyName,typeof(string),?null);
????????????this.OnListChanged(new?ListChangedEventArgs(listChangedType,?index,propDesc));
????????}
????????/**////?<summary>?返回/設置是否引發ListChanged中ItemChanged項目?</summary>
????????public?bool?RaiseItemChangedEvents
????????{
????????????get
????????????{
????????????????return?this.hookingItems;
????????????}
????????????set
????????????{
????????????????if?(this.hookingItems?!=?value)
????????????????{
????????????????????this.HookItems(false);
????????????????????this.hookingItems?=?value;
????????????????????this.HookItems(true);
????????????????}
????????????}
????????}
????????/**////?<summary>?引發重新更新事件?</summary>
????????public?void?ResetBindings()
????????{
????????????this.FireListChanged(ListChangedType.Reset,?-1);
????????}
????????/**////?<summary>?引發某個元素的改動事件?</summary>
????????public?void?ResetItem(int?position)
????????{
????????????this.FireListChanged(ListChangedType.ItemChanged,?position);
????????}
????????//攔截/取消元素
????????private?void?HookItem(object?item,?bool?hook)
????????{
????????????if?(!this.hookingItems)
????????????{
????????????????return;
????????????}
????????????if?(this.onItemPropertyChanged?==?null)
????????????{
????????????????this.onItemPropertyChanged?=?new?PropertyChangedEventHandler(this.OnItemPropertyChanged);
????????????}
????????????IPropertyChange?tmp?=?item?as?IPropertyChange;
????????????if?(tmp?!=?null)
????????????{
????????????????if?(hook)
????????????????????tmp.PropertyChanged?+=?this.onItemPropertyChanged;
????????????????else
????????????????????tmp.PropertyChanged?-=?this.onItemPropertyChanged;
????????????}
????????}
????????//攔截/取消指定索引的元素
????????private?void?HookItemAt(int?index,?bool?hook)
????????{
????????????if?((this.hookingItems?&&?(index?>=?0))?&&?(index?<?base.Count))
????????????{
????????????????this.HookItem(base.List[index],?hook);
????????????}
????????}
????????//攔截/取消所有元素
????????private?void?HookItems(bool?hook)
????????{
????????????if?(!this.hookingItems)
????????????????return;
????????????IEnumerator?e?=?base.GetEnumerator();
????????????while?(e.MoveNext())
????????????{
????????????????object?tmp?=?e.Current;
????????????????this.HookItem(tmp,?hook);
????????????}
????????}
????????//在元素發生改變時調用
????????private?void?OnItemPropertyChanged(object?sender,?PropertyChangedEventArgs?e)
????????{
????????????this.FireListChanged(ListChangedType.ItemChanged,?base.List.IndexOf(sender),?e.PropertyName);
????????}
????????#endregion
????????Clear相關方法#region?Clear相關方法
????????/**////?<summary>?在清除?DataRowCollectionBase?中所有實例之前執行其他自定義進程。</summary>
????????protected?override?void?OnClear()
????????{
????????????this.EndNew(this.addNewPos);
????????????this.HookItems(false);
????????????//刪除父對象關聯,注意:這里不能會滾操作
????????????DataRowBase?row;
????????????foreach?(object?item?in?InnerList)
????????????{
????????????????row?=?item?as?DataRowBase;
????????????????if?(row?!=?null)
????????????????????row.SetParent(null);
????????????}
????????????base.OnClear();
????????}
????????/**////?<summary>?在清除?DataRowCollectionBase?中所有實例之后執行其他自定義進程。?</summary>
????????protected?override?void?OnClearComplete()
????????{
????????????base.OnClearComplete();
????????????this.FireListChanged(ListChangedType.Reset,?-1);
????????}
????????#endregion
????????Remove相關方法#region?Remove相關方法
????????/**////?<summary>?在向?DataRowCollectionBase?實例中移出元素之前執行其他自定義進程。?</summary>
????????protected?override?void?OnRemove(int?index,?object?value)
????????{
????????????this.EndNew(this.addNewPos);
????????????this.HookItemAt(index,?false);
????????????base.OnRemove(index,?value);
????????}
????????/**////?<summary>?在向?DataRowCollectionBase?實例中移出元素之后執行其他自定義進程。?</summary>
????????protected?override?void?OnRemoveComplete(int?index,?object?value)
????????{
????????????//刪除父對象關聯
????????????DataRowBase?row?=?value?as?DataRowBase;
????????????if?(row?!=?null)
????????????????row.SetParent(null);
????????????base.OnRemoveComplete(index,?value);
????????????this.FireListChanged(ListChangedType.ItemDeleted,?index);
????????}
????????#endregion
????????Set相關方法#region?Set相關方法
????????/**////?<summary>?當在?DataRowCollectionBase?實例中設置值后執行其他自定義進程。</summary>
????????protected?override?void?OnSetComplete(int?index,?object?oldValue,?object?newValue)
????????{
????????????//刪除舊對象的父對象
????????????DataRowBase?oldRow?=?oldValue?as?DataRowBase;
????????????if?(oldRow?!=?null)
????????????????oldRow.SetParent(null);
????????????//設置新對象的父對象
????????????DataRowBase?newRow?=?newValue?as?DataRowBase;
????????????if?(newRow?!=?null)
????????????????newRow.SetParent(_parent);
????????????base.OnSetComplete(index,?oldValue,?newValue);
????????????this.FireListChanged(ListChangedType.ItemChanged,?index);
????????}
????????#endregion
????????ICancelAddNew支持#region?ICancelAddNew支持
????????/**////?<summary>?取消新建的行?</summary>
????????public?void?CancelNew(int?itemIndex)
????????{
????????????if?((this.addNewPos?>=?0)?&&?(this.addNewPos?==?itemIndex))
????????????{
????????????????this.RemoveAt(this.addNewPos);
????????????????this.addNewPos?=?-1;
????????????}
????????}
????????/**////?<summary>?結束新建行的編輯?</summary>
????????public?void?EndNew(int?itemIndex)
????????{
????????????if?((this.addNewPos?>=?0)?&&?(this.addNewPos?==?itemIndex))
????????????{
????????????????this.addNewPos?=?-1;
????????????}
????????}
????????#endregion
????????集合是否可以改動的支持#region?集合是否可以改動的支持
????????/**////?<summary>?獲取/設置是否可以使用?AddNew?向列表中添加項。?</summary>
????????public?bool?AllowNew
????????{
????????????get
????????????{
????????????????return?((IBindingList)this).AllowNew;
????????????}
????????????set
????????????{
????????????????this.allowNew?=?value;
????????????}
????????}
????????/**////?<summary>?獲取是否可以使用?AddNew?向列表中添加項。?</summary>
????????bool?IBindingList.AllowNew
????????{
????????????get
????????????{
????????????????return?this.AllowNewCore;
????????????}
????????}
????????/**////?<summary>?獲取是否可以使用?AddNew?向列表中添加項。?</summary>
????????protected?virtual?bool?AllowNewCore
????????{
????????????get
????????????{
????????????????return?this.allowNew;
????????????}
????????}
????????/**////?<summary>?獲取/設置是否可更新列表中的項。?</summary>
????????public?bool?AllowEdit
????????{
????????????get
????????????{
????????????????return?((IBindingList)this).AllowEdit;
????????????}
????????????set
????????????{
????????????????this.allowEdit?=?value;
????????????}
????????}
????????/**////?<summary>?獲取是否可更新列表中的項。</summary>
????????bool?IBindingList.AllowEdit
????????{
????????????get
????????????{
????????????????return?this.AllowEditCore;
????????????}
????????}
????????/**////?<summary>?獲取是否可更新列表中的項。?</summary>
????????protected?virtual?bool?AllowEditCore
????????{
????????????get
????????????{
????????????????return?this.allowEdit;
????????????}
????????}
????????/**////?<summary>?獲取/設置是否可以使用?Remove?或?RemoveAt?從列表中移除項。?</summary>
????????public?bool?AllowRemove
????????{
????????????get
????????????{
????????????????return?((IBindingList)this).AllowRemove;
????????????}
????????????set
????????????{
????????????????this.allowRemove?=?value;
????????????}
????????}
????????/**////?<summary>?獲取是否可以使用?Remove?或?RemoveAt?從列表中移除項。?</summary>
????????bool?IBindingList.AllowRemove
????????{
????????????get
????????????{
????????????????return?this.AllowRemoveCore;
????????????}
????????}
????????/**////?<summary>?獲取是否可以使用?Remove?或?RemoveAt?從列表中移除項。?</summary>
????????protected?virtual?bool?AllowRemoveCore
????????{
????????????get
????????????{
????????????????return?this.allowRemove;
????????????}
????????}
????????#endregion
????????排序和查詢功能的支持#region?排序和查詢功能的支持
????????/**////?<summary>?獲取當列表更改或列表中的項更改時是否引發?ListChanged?事件。?</summary>
????????public?bool?SupportsChangeNotification
????????{
????????????get
????????????{
????????????????return?this.SupportsChangeNotificationCore;
????????????}
????????}
????????/**////?<summary>?獲取當列表更改或列表中的項更改時是否引發?ListChanged?事件。?</summary>
????????protected?virtual?bool?SupportsChangeNotificationCore
????????{
????????????get
????????????{
????????????????return?true;
????????????}
????????}
????????/**////?<summary>?獲取列表是否支持使用?Find?方法進行搜索。?</summary>
????????public?bool?SupportsSearching
????????{
????????????get
????????????{
????????????????return?this.SupportsSearchingCore;
????????????}
????????}
????????/**////?<summary>?獲取列表是否支持使用?Find?方法進行搜索。?</summary>
????????protected?virtual?bool?SupportsSearchingCore
????????{
????????????get
????????????{
????????????????return?false;
????????????}
????????}
????????/**////?<summary>?獲取列表是否支持排序?</summary>
????????public?bool?SupportsSorting
????????{
????????????get
????????????{
????????????????return?this.SupportsSortingCore;
????????????}
????????}
????????/**////?<summary>?獲取列表是否支持排序?</summary>
????????protected?virtual?bool?SupportsSortingCore
????????{
????????????get
????????????{
????????????????return?false;
????????????}
????????}
????????/**////?<summary>?獲取是否對列表中的項進行排序。</summary>
????????public?bool?IsSorted
????????{
????????????get
????????????{
????????????????return?this.IsSortedCore;
????????????}
????????}
????????/**////?<summary>?獲取是否對列表中的項進行排序。?</summary>
????????protected?virtual?bool?IsSortedCore
????????{
????????????get
????????????{
????????????????return?false;
????????????}
????????}
????????/**////?<summary>?獲取正在用于排序的?PropertyDescriptor。?</summary>
????????public?PropertyDescriptor?SortProperty
????????{
????????????get
????????????{
????????????????return?this.SortPropertyCore;
????????????}
????????}
????????/**////?<summary>?獲取正在用于排序的?PropertyDescriptor。?</summary>
????????protected?virtual?PropertyDescriptor?SortPropertyCore
????????{
????????????get
????????????{
????????????????return?null;
????????????}
????????}
????????/**////?<summary>?獲取排序的方向。?</summary>
????????public?ListSortDirection?SortDirection
????????{
????????????get
????????????{
????????????????return?this.SortDirectionCore;
????????????}
????????}
????????/**////?<summary>?獲取排序的方向。</summary>
????????protected?virtual?ListSortDirection?SortDirectionCore
????????{
????????????get
????????????{
????????????????return?ListSortDirection.Ascending;
????????????}
????????}
????????/**////?<summary>?根據?PropertyDescriptor?和?ListSortDirection?對列表進行排序。?</summary>
????????public?void?ApplySort(PropertyDescriptor?property,?ListSortDirection?direction)
????????{
????????????this.ApplySortCore(property,?direction);
????????}
????????/**////?<summary>?根據?PropertyDescriptor?和?ListSortDirection?對列表進行排序。?</summary>
????????protected?virtual?void?ApplySortCore(PropertyDescriptor?property,?ListSortDirection?direction)
????????{
????????????throw?new?NotSupportedException();
????????}
????????/**////?<summary>?使用?ApplySort?移除任何已應用的排序。?</summary>
????????public?void?RemoveSort()
????????{
????????????this.RemoveSortCore();
????????}
????????/**////?<summary>?使用?ApplySort?移除任何已應用的排序。</summary>
????????protected?virtual?void?RemoveSortCore()
????????{
????????????throw?new?NotSupportedException();
????????}
????????/**////?<summary>?返回具有給定?PropertyDescriptor?的行的索引。?</summary>
????????public?int?Find(PropertyDescriptor?property,?object?key)
????????{
????????????return?this.FindCore(property,?key);
????????}
????????/**////?<summary>?返回具有給定?PropertyDescriptor?的行的索引。?</summary>
????????protected?virtual?int?FindCore(PropertyDescriptor?property,?object?key)
????????{
????????????throw?new?NotSupportedException();
????????}
????????/**////?<summary>?將?PropertyDescriptor?添加到用于搜索的索引?</summary>
????????void?IBindingList.AddIndex(PropertyDescriptor?property)
????????{
????????????//
????????}
????????/**////?<summary>?從用于搜索的索引中移除?PropertyDescriptor。?</summary>
????????void?IBindingList.RemoveIndex(PropertyDescriptor?property)
????????{
????????????//
????????}
????????#endregion
????}
}
總結
以上是生活随笔為你收集整理的回复 寒枫天伤 - PSP 的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 敏捷开发:软件与文档
- 下一篇: IronSoft ASP系列组件,年前最