程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則41:選擇DataSet而不是自定義的數據結構(3)

Effective C#原則41:選擇DataSet而不是自定義的數據結構(3)

編輯:關於C語言

為了在我們自己定義的集合上也實現這樣 的概念,我們很要做點工作。你要修改你的AddressRecord 結構來支持兩個新的 接口,IEditableObject 和IDataErrorInfo。IEditableObject 為你的類型提供 了對事務的支持。IDataErrorInfo 提供了常規的錯誤處理。為了支持事務,你 必須修改你的數據存儲來提供你自己的回滾功能。你可能在多個列上有錯誤,因 此你的存儲必須包含一個包含了每個列的錯誤集合。這是一個為AddressRecord 做的更新的列表:

public class AddressRecord : IEditableObject, IDataErrorInfo
{
  private struct AddressRecordData
  {
   public string street;
    public string city;
   public string state;
    public string zip;
  }
  private AddressRecordData permanentRecord;
  private AddressRecordData tempRecord;
  private bool _inEdit = false;
  private IList _container;
  private Hashtable errors = new Hashtable();
  public AddressRecord( AddressList container )
  {
    _container = container;
  }
  public string Street
  {
   get
   {
    return ( _inEdit ) ? tempRecord.street :
     permanentRecord.street;
    }
   set
   {
    if ( value.Length == 0 )
     errors[ "Street" ] = "Street cannot be empty";
    else
    {
      errors.Remove( "Street" );
    }
    if ( _inEdit )
     tempRecord.street = value;
     else
    {
     permanentRecord.street = value;
     int index = _container.IndexOf( this );
      _container[ index ] = this;
    }
   }
  }
  public string City
  {
   get
   {
    return ( _inEdit ) ? tempRecord.city :
      permanentRecord.city;
   }
   set
   {
     if ( value.Length == 0 )
     errors[ "City" ] = "City cannot be empty";
    else
     {
     errors.Remove( "City" );
    }
    if ( _inEdit )
     tempRecord.city = value;
    else
    {
     permanentRecord.city = value;
     int index = _container.IndexOf( this );
      _container[ index ] = this;
    }
   }
  }
  public string State
  {
   get
    {
    return ( _inEdit ) ? tempRecord.state :
      permanentRecord.state;
   }
   set
   {
    if ( value.Length == 0 )
     errors[ "State" ] = "City cannot be empty";
     else
    {
     errors.Remove( "State" );
    }
    if ( _inEdit )
      tempRecord.state = value;
    else
    {
      permanentRecord.state = value;
     int index = _container.IndexOf( this );
     _container[ index ] = this;
    }
   }
  }
  public string Zip
  {
   get
   {
    return ( _inEdit ) ? tempRecord.zip :
     permanentRecord.zip;
   }
   set
   {
    if ( value.Length == 0 )
     errors["Zip"] = "Zip cannot be empty";
    else
    {
      errors.Remove ( "Zip" );
    }
    if ( _inEdit )
     tempRecord.zip = value;
    else
    {
     permanentRecord.zip = value;
      int index = _container.IndexOf( this );
     _container[ index ] = this;
    }
   }
  }
  public void BeginEdit( )
  {
   if ( ( ! _inEdit ) && ( errors.Count == 0 ) )
    tempRecord = permanentRecord;
   _inEdit = true;
  }
  public void EndEdit( )
  {
   // Can't end editing if there are errors:
   if ( errors.Count > 0 )
    return;
   if ( _inEdit )
    permanentRecord = tempRecord;
    _inEdit = false;
  }
  public void CancelEdit( )
   {
   errors.Clear( );
   _inEdit = false;
   }
  public string this[string columnName]
  {
    get
   {
    string val = errors[ columnName ] as string;
    if ( val != null )
     return val;
    else
     return null;
   }
  }
  public string Error
  {
   get
   {
    if ( errors.Count > 0 )
    {
      System.Text.StringBuilder errString = new
       System.Text.StringBuilder();
     foreach ( string s in errors.Keys )
     {
      errString.Append( s );
      errString.Append( ", " );
      }
     errString.Append( "Have errors" );
     return errString.ToString( );
    }
     else
     return "";
   }
  }
 }

花了幾頁的代碼來支持一些已經在DataSet裡實現的了的功能 。實際上,這還不能像DataSet那樣恰當的工作。例如,交互式的添加一個新記 錄到集合中,以及支持事務所要求的BeginEdit, CancelEdit, 和EndEdit等。 你要在CancelEdit 調用時檢測一個新的對象而不是一個已經修改了的對象。 CancelEdit 必須從集合上移除這個新的對象,該對象應該是上次調用BeginEdit 時創建的。對於AddressRecord 來說,還有很多修改要完成,而且一對事件還要 添加到AddressList 類上。

最後,就是這個IBindingList接口。這個接 口至少包含了20個方法和屬性,用於控件查詢列表上的功能描述。你必須為只讀 列表實現IBindingList 或者交互排序,或者支持搜索。在你取得內容之前就陷 於層次關系和導航關系中了。我也不准備為上面所有的代碼添加任何例子了。

幾頁過後,再問問你自己,還准備創建你自己的特殊集合嗎?或者你想 使用一個DataSet嗎?除非你的集合是一個基於某些算法,對性能要求嚴格的集 合,或者必須有輕便的格式,就要使用自己的DataSet,特別是類型化的DataSet 。這將花去你大量的時間,是的,你可以爭辯說DataSet並不是一個基於面向對 象設計的最好的例子。類型化的DataSet甚至會破壞更多的規則。但,使用它所 產生的代碼開發效率,比起自己手寫更優美的代碼所花的時間,這只是其中一小 部份。

返回教程目錄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved