处理数据之前数据源所包含元素的总数,而GetPagedData方法返回原始数据的一个子集,例如:假设数据源是一个包含20个元素的数组,分页控件将数据显示成每页10个元素,则第一页的元素子集是数组元素0-9,第二页的元素子集是数组元素10-19。DataViewAdapter提供了一个DataView类型的插头:
internal class DataViewAdapter:IDataSourceAdapter
{
private DataView _view;
internal DataViewAdapter(DataView view)
{
_view = view;
}
public int TotalCount
{
get{return (_view == null) ? 0 : _view.Table.Rows.Count;}
}
public object GetPagedData(int start, int end)
{
DataTable table = _view.Table.Clone();
for (int i = start;i<=end && i<= TotalCount;i++)
{
table.ImportRow(_view[i-1].Row);
}
return table;
}
}
DataViewAdapter实现了IDataSourceAdapter的GetPagedData方法,该GetPagedData克隆原始的DataTable,将原始DataTable中的数据导入到新的DataTable。该类的可见性有意地设置成internal,目的是为了向Web开发者隐藏实现细节,进而通过Builder类提供一个更简单的接口。
public abstract class AdapterBuilder
{
private object _source;
private void CheckForNull()
{
if (_source == null) throw new NullReferenceException("必须提供一个合法的数据源");
}
public virtual object Source
{
get
{
CheckForNull();
return _source;}
set
{
_source = value;
CheckForNull();
}
}
public abstract IDataSourceAdapter Adapter{get;}
}
AdapterBuilder抽象类为IdataSourceAdapter类型提供了一个更容易管理的接口,由于提高了抽象程度,我们不必再直接使用IdataSourceAdapter,同时AdapterBuilder还提供了在分页数据之前执行预处理的指令。另外,该Builder还使得实际的实现类,例如DataViewAdapter,对分页控件的用户透明:
public class DataTableAdapterBuilder:AdapterBuilder
{
private DataViewAdapter _adapter;
private DataViewAdapter ViewAdapter
{
get
{
if (_adapter == null)
{
DataTable table = (DataTable)Source;
_adapter = new DataViewAdapter(table.DefaultView);
}
return _adapter;
}
}
public override IDataSourceAdapter Adapter
{
get
{
return ViewAdapter;
}
}
}
public class DataViewAdapterBuilder:AdapterBuilder
{
private DataViewAdapter _adapter;
private DataViewAdapter ViewAdapter
{
get
{ // 延迟实例化
if (_adapter == null)
{
_adapter = new DataViewAdapter((DataView)Source);
}
return _adapter;
}
}
public override IDataSourceAdapter Adapter
{
get{return ViewAdapter;}
}
}
DataView类型和DataTable类型的关系是如此密切,所以构造一个通用性的DataAdapter可能是有意义的,其实只要加入另一个处理DataTable的构造函数就足够了。遗憾的是,当用户需要不同的功能来处理某个DataTable时,就必须替换或继承整个类。如果我们构造一个使用同一IdataSourceAdapter的新Builder,用户在选择如何实现适配器时就拥有更多的自由。
在分页控件中,寻找适当Builder类的操作由一个类型安全的集合完成。
public class AdapterCollection:DictionaryBase
{
private string GetKey(Type key)
{
return key.FullName;
}
public AdapterCollection() {}
publicvoid Add(Type key,AdapterBuilder value)
{
Dictionary.Add(GetKey(key),value);
}
publicbool Contains(Type key)
{
return Dictionary.Contains(GetKey(key));
}
publicvoid Remove(Type key)
{
Dictionary.Remove(GetKey(key));
}
public AdapterBuilder this[Type key
|