WEB开发网
开发学院软件开发C语言 Effective C# 原则41:选择DataSet而不是自定义的... 阅读

Effective C# 原则41:选择DataSet而不是自定义的数据结构

 2009-02-19 08:17:41 来源:WEB开发网   
核心提示: 为了在我们自己定义的集合上也实现这样的概念,我们很要做点工作,Effective C# 原则41:选择DataSet而不是自定义的数据结构(4),你要修改你的AddressRecord 结构来支持两个新的接口,IEditableObject 和IDataErrorInfo,使用它所产生的代

为了在我们自己定义的集合上也实现这样的概念,我们很要做点工作。你要修改你的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 3 4 

Tags:Effective 原则 选择

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接