ReadOnlyListBase类主要用来管理业务对象集合,并且是个只读的,在Web开发中比较适合,我们一般很少有可编辑的业务对象集合。ReadOnlyListBase返回的是强类型的业务对象实体集合。可以作为任何需要数据绑定的web控件上。
ReadOnlyListBase与CSLA.NET的数据访问接口通过DataPortal.Fetch来得到数据。因为只一个Fetch方法,当继承此类的业务对象时有许多得到数据的方法,比如得到所有数据GetALL、得到某个部门下的所有子部门等,既对业务对象要求从不同角度来得到数据。为了解决这个问题,让我伤了点脑筋。先看下
DataPortal.Fetch的声明如下:
public static T Fetch<T>(object criteria);
只有一个条件参数,你可以考虑重载很多方法,但不能根本解决问题,因为有时只用参数类型或个数的不同来重载会出现重复的现在,所有重载不能解决有问题。我最后实现的方法来为,实现一个继承自Csla.CriteriaBase的类CriteriaHash,只重载一个private void DataPortal_Fetch(CriteriaHash criteria)方法,通过CriteriaHash的内容来判断具体调用那个方法及参数的获取。
CriteriaHash主要用一个数组来保存本次操作的类型及所有参数值得,这样可以解决传递多个参数及值的问题。用一个Dictionary<string, object>来保存数据值,可以使用索引器来访问,Key表示参数变量,Value为参数的值。并且约定数组的第一个为操作类型,后边为所有参数及值的表。
/// <summary>
/// 条件判断类
/// CriteriaHash必须继承Csla.CriteriaBase,不然在数据在服务器和客户端移动时会出问题。
/// 我按书说的方法不继承,总是出错。
/// </summary>
[Serializable()]
public class CriteriaHash : CriteriaBase
{
Dictionary<string, object> _dic;
//基类使用
public CriteriaHash(Type type)
: base(type)
{
}
public CriteriaHash(Type type, CriteriaItems[] filters)
: base(type)
{
_dic = new Dictionary<string, object>();
foreach (CriteriaItems f in filters)
{
_dic.Add(f.ParmName, f.value);
}
}
public object this[string Key]
{
get
{
if (_dic.ContainsKey(Key))
return _dic[Key];
else
return null;
}
}
}
[Serializable()]
public class CriteriaItems
{
private readonly string _parmName;
public CriteriaItems(string parmName, object value)
{
_parmName = parmName;
this.value = value;
}
public object value { get; private set; }
public string ParmName
{
get { return _parmName; }
}
}// http://blog.csdn.net/dacong
下边以单位信息表类SHOP_INFOList来具体说明
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Csla;
using Csla.Data;
[Serializable()]
public partial class SHOP_INFOList : Csla.ReadOnlyListBase<SHOP_INFOList, SHOP_INFOInfo>
{
/// <summary>
/// 操作类型枚举定义,
/// 为了标识所有包括的方法
/// </summary>
private enum OperationType { GetAll,GetAllLevel, GetByShopId };
#region Factory Methods
/// <summary>
/// 得到一个空的对象
/// </summary>
/// <returns></returns>
public static SHOP_INFOList EmptyList()
{
return new SHOP_INFOList();
}
/// <summary>
/// 得到所有单位信息
/// </summary>
/// <returns></returns>
public static SHOP_INFOList GetALL()
{
return DataPortal.Fetch<SHOP_INFOList>(new CriteriaHash(typeof(SHOP_INFOList),new CriteriaItems[] { new CriteriaItems("OperationType", OperationType.GetAll) }));
/*
* 注意Fetch参数的构造,new CriteriaItems[]数据,第一个元素表示操作的类型,也就是方法的名称,如果没有参数只构造一个就可以
* 如果有参数构造如:new CriteriaItems("ShopId", shopId),"ShopId":参数变量名,shopId,变量的值
*
*/
}
public static SHOP_INFOList GetALLForLevel()
{
return DataPortal.Fetch<SHOP_INFOList>(new CriteriaHash(typeof(SHOP_INFOList), new CriteriaItems[] { new CriteriaItems("OperationType", OperationType.GetAllLevel) }));
}
/// <summary>
/// 得到当前SHOP_ID下的所有子部门
/// </summary>
/// <param name="shopId"></param>
/// <returns></returns>
public static SHOP_INFOList GetByShopId(string shopId)
{
return DataPortal.Fetch<SHOP_INFOList>(new CriteriaHash(typeof(SHOP_INFOList), new CriteriaItems[] { new CriteriaItems("OperationType", OperationType.GetByShopId), new CriteriaItems("ShopId", shopId) }));
}
private SHOP_INFOList()
{ /* require use of factory methods */
}
#endregion
#region Data Access
#region 具体方法实现
private void _GetALL()
{
var dal = new SHOP_INFODal();
Fill(dal.GetAll(), 0, 0);
}
private void _GetALLForLevel()
{
Fill(new SHOP_INFODal().GetTreeLevel(), 0, 0);
}
private void _GetByShopId(string shopId)
{
//具体怎么实现,根据自己的DAL
var dal = new SHOP_INFODal();
Fill(dal.GetBySHOP_ID(shopId,true), 0, 0);
}
#endregion
#region Data Access - Fetch dispatch
/// <summary>
/// 根据SafeDataReader来填充业务对象
/// </summary>
/// <param name="reader"></param>
/// <param name="start"></param>
/// <param name="pageLength"></param>
private void Fill(SafeDataReader reader, int start, int pageLength)
{
// advance to the starting row
for (int i = 0; i < start; i++)
{
if (!reader.Read())
return; // not enough rows, just return
}
RaiseListChangedEvents = false;
IsReadOnly = false;
if (pageLength <= 0)
pageLength = int.MaxValue;
SHOP_INFOInfo data = null;
//得到所有字段列表
List<string> fields = new List<string>();
for (int i = 0; i < reader.FieldCount; i++)
{
fields.Add(reader.GetName(i));
}
for (int i = 0; i < pageLength; i++)
{
if (!reader.Read())
break; // we are done
data = new SHOP_INFOInfo();
if (fields.IndexOf("SHOP_ID") >= 0)
data.SHOP_ID = reader.GetString("SHOP_ID");
if (fields.IndexOf("UP_SHOP_ID") >= 0)
data.UP_SHOP_ID = reader.GetString("UP_SHOP_ID");
if (fields.IndexOf("SHOP_NAME") >= 0)
data.SHOP_NAME = reader.GetString("SHOP_NAME");
if (fields.IndexOf("SHOP_ABBRE") >= 0)
data.SHOP_ABBRE = reader.GetString("SHOP_ABBRE");
if (fields.IndexOf("POST_ADDR") >= 0)
data.POST_ADDR = reader.GetString("POST_ADDR");
if (fields.IndexOf("SHOP_TYPE") >= 0)
data.SHOP_TYPE = reader.GetString("SHOP_TYPE");
if (fields.IndexOf("POST_CODE") >= 0)
data.POST_CODE = reader.GetString("POST_CODE");
if (fields.IndexOf("PRINCIPAL") >= 0)
data.PRINCIPAL = reader.GetString("PRINCIPAL");
if (fields.IndexOf("TELEPHONE") >= 0)
data.TELEPHONE = reader.GetString("TELEPHONE");
if (fields.IndexOf("MOBILE") >= 0)
data.MOBILE = reader.GetString("MOBILE");
if (fields.IndexOf("NOTES") >= 0)
data.NOTES = reader.GetString("NOTES");
this.Add(data);
}
IsReadOnly = true;
RaiseListChangedEvents = true; // http://blog.csdn.net/dacong
}
/// <summary>
/// 数据访问接口
/// </summary>
/// <param name="criteria"></param>
private void DataPortal_Fetch(CriteriaHash criteria)
{
OperationType operationType = (OperationType)criteria["OperationType"];
//根据操作类型来分发,调具体的实现方法
switch (operationType)
{
case OperationType.GetAll:
_GetALL();
break;
case OperationType.GetAllLevel:
_GetALLForLevel();
break;
case OperationType.GetByShopId:
_GetByShopId(criteria["ShopId"].ToString());
break;
default:
break;
}
}
#endregion //Data Access - Fetch
#endregion // Data Access
}
//只读业务对象
[Serializable()]
public partial class SHOP_INFOInfo : Csla.ReadOnlyBase<SHOP_INFOInfo>
{
//http://blog.csdn.net/dacong
public string SHOP_ID { get; internal set; }
public string UP_SHOP_ID { get; internal set; }
public string SHOP_NAME { get; internal set; }
public string SHOP_ABBRE { get; internal set; }
public string POST_ADDR { get; internal set; }
public string SHOP_TYPE { get; internal set; }
public string POST_CODE { get; internal set; }
public string PRINCIPAL { get; internal set; }
public string TELEPHONE { get; internal set; }
public string MOBILE { get; internal set; }
public string NOTES { get; internal set; }
}
此方法只是我目前想到的一个方案,共现出来及大家交流。
2009-6-11 哈尔滨