例子说明修改bm
[MaxLabs.bbsMax]
逻辑层,用来放 单个实体类(Entity)、实体集合类(Collection) 、抽象类(Dao)、逻辑处理类(BO)
单个实体类(Entity)、实体集合类(Collection)都放在“Features” \ 对象名 \ “Entities” 目录下。
按照bbsmax的框架结构,实体的集合,都应放在 实体集合类(Collection)中,它类似于(List<TV>). 实现了:
“ICollection<TV>“, ”IComparable<TK> ,“IPrimaryKey<TK>”,"IEnumerable", "IEnumerable<TV>"接口.
因此它:
1.可迭代、枚举
2.可对比
它内部是用一个List<TV>泛型实例存放对象(实例名innerList)
List<TV> innerList;
它包含一个int下标的类索引
public virtual TV this[int index]
还包含名为Count的 get访问器<int>,以返回List<TV>的数据条数。
public virtual int Count
{
get { return innerList.Count; }
}
因此它:
1.可通过for int递增循环访问。
2.可通过int类型的下标访问。
3.它不可以通过TK(如string key)键索引的方式访问,因为 List<TV>只能通过int下标访问。
抽象类(Dao) ,用于存放对诸如帖子、板块 的数据访问抽象方法,都放在“Features” \ 对象名 \ “DataAccess” 目录下。
BO类,用于调用各 抽象类(Dao)的实现类实例。
以上类全部是实例类。
[MaxLabs.bbsMax.Web]
界面层,Web项目,在 bbsmax[5.1008]版本中,各aspx页面的后置代码都放在 "_codes"文件夹下 。
bbsmax的每一个aspx页面的后置代码都继承自一个PageBase(页面基类)。
如论坛首页"index.aspx","default.aspx" 页面的后置代码:
//_Default论坛index.aspx首页的后置代码,继承了bbs页面基类
public partial class _Default : AppBbsPageBase
{
//省略无关代码...
}
//bbs页面基类
public class BbsPageBase : WebEngine.PageBase
{
//论坛板块集合访问器
protected ForumCollection ForumCatalogs
{
get{
if (m_ForumCatalogs == null)
{
//调用对应逻辑类(BO)实例的对应查询方法
m_ForumCatalogs = ForumBO.Instance.GetCategories();
}
return m_ForumCatalogs;
}
}
}
这样继承之后,我在"index.aspx" 页面就能获取到“ForumCatalogs”变量了,我只要遍历它,就能在页面上显示所有板块信息了。
既然如此,那么对应" default.aspx "模板代码里的以下代码:
<!--[if $ForumCatalogs.Count > 0]-->
<!--[loop $forumCatalog in $ForumCatalogs with $LoopIndex]-->
<a href="$url($forumCatalog.CodeName/list-1)">$forumCatalog.ForumName</a>
<!--[/loop]-->
<!--[/if]-->
[MaxLabs.bbsMax.DataAccess.SqlServer]
数据访问层, 实现" [MaxLabs.bbsMax]"层 的抽象类中的抽象方法,操控数据库。
项目介绍完毕。
------
整个过程如下:
1.新建一个数据表,用来存放所需数据。
2.创建一个 对应的实例类和 实例集合类。
3.创建一个抽象类(Dao),用于存放查询数据库的抽象方法。
4.创建一个数据库访问类, 实现" [MaxLabs.bbsMax]"层 的抽象类中的抽象方法。
5.创建一个逻辑类 (BO) ,调用抽象类(Dao)的实现类实例 。
6.在"BbsPageBase"页面基类添加一个对应的集合变量访问器,访问器的get方法就是返回查询到的数据。
7.在模板中调用该访问器。
代码:
using System;
using System.Collections.Generic;
using System.Text;
using MaxLabs.bbsMax.Enums;
using MaxLabs.bbsMax.DataAccess;
using MaxLabs.bbsMax.Settings;
namespace MaxLabs.bbsMax.Entities
{
/// <summary>
/// 全局模板变量[实体类]
/// </summary>
public class TemplateVar : IPrimaryKey<string>
{
string _hash;
string _value;
int _tvarid;
public TemplateVar()
{
_hash = string.Empty;
_value = string.Empty;
_tvarid = -1;
}
/// <summary>
/// 从数据库data对象中,取出数据,封装为对象。
/// </summary>
/// <param name="__readerWrap"></param>
public TemplateVar(DataReaderWrap __readerWrap)
{
_tvarid = __readerWrap.Get<int>("tvarid");
_value = __readerWrap.Get<string>("value");
_hash = __readerWrap.Get<string>("hash");
}
/// <summary>
/// 对应数据表字段[hash]
/// </summary>
public string Hash
{
get { return _hash; }
set { _hash = value; }
}
/// <summary>
/// 对应数据表字段[value]
/// </summary>
public string Value
{
get { return _value; }
set { _value = value; }
}
/// <summary>
/// 对应数据表字段[tvarid]
/// </summary>
public int Tvarid
{
get { return _tvarid; }
set { _tvarid = value; }
}
/// <summary>
/// 重写ToString()方法,这里很重要。
/// </summary>
/// <returns>用户自定义的变量值</returns>
public override string ToString()
{
return _value;
}
//这个可以无视
#region IPrimaryKey<string> 成员
public string GetKey()
{
return _hash;
}
#endregion
}
}
由于我们需要通过 string key/键 的方式来得到“全局模板变量”实体对象的值,因此,bbsmax框架的 “实体集合”类是不适合的,
我们需要自己写支持通过string key/键 “实体集合类” 来存放“全局模板变量”。
我们可以直接用.net 自带的 键/值 字典集合 Dictionary<string,TemplateVar> 类,它支持通过 string key/键 的方式来得到“全局模板变量”实体对象的值 不过这样显然与bbsmax的框架格格不入,因此,我们自己写 “实体集合类”。
你要知道,它的本质就是基于 Dictionary<TK, TV>,只不过是一个 Dictionary<TK, TV>的再次封装,这样虽然更麻烦,但会变得很灵活,和可扩展,比如:你可以在自定义的 “实体集合类” 里面加一个“只读”属性。
using System;
using System.Collections;
using System.Collections.Generic;
namespace MaxLabs.bbsMax.Entities
{
/// <summary>
/// 基于键/值的字典集合
/// </summary>
/// <typeparam name="TK">键</typeparam>
/// <typeparam name="TV">值</typeparam>
public abstract class EntityDictionaryBase<TK, TV> : IDictionary<TK, TV>, IEnumerable, IEnumerable<KeyValuePair<TK, TV>>
{
private bool m_IsReadOnly = false;
bool _isIgnoreItemNotExist;
//集合
Dictionary<TK, TV> dictionay;
public EntityDictionaryBase()
{
dictionay = new Dictionary<TK, TV>();
}
public EntityDictionaryBase(bool __isIgnoreItemNotExist)
{
this._isIgnoreItemNotExist = __isIgnoreItemNotExist;
dictionay = new Dictionary<TK, TV>();
}
public virtual void Clear()
{
if (m_IsReadOnly)
{
throw new NotSupportedException("Collection is readonly.");
}
dictionay.Clear();
}
public virtual bool IsReadOnly
{
get { return m_IsReadOnly; }
}
#region IDictionary<TK,TV> 成员
public virtual void Add(TK key, TV value)
{
if (m_IsReadOnly)
{
throw new NotSupportedException("Collection is readonly.");
}
dictionay.Add(key, value);
}
public virtual bool ContainsKey(TK key)
{
return dictionay.ContainsKey(key);
}
public virtual ICollection<TK> Keys
{
get { return dictionay.Keys; }
}
public virtual bool Remove(TK key)
{
return dictionay.Remove(key);
}
public virtual bool TryGetValue(TK key, out TV value)
{
return dictionay.TryGetValue(key, out value);
}
public virtual ICollection<TV> Values
{
get { return dictionay.Values; }
}
public virtual TV this[TK key]
{
get
{
return dictionay[key];
}
set
{
dictionay[key] = value;
}
}
#endregion
#region ICollection<KeyValuePair<TK,TV>> 成员
public virtual void Add(KeyValuePair<TK, TV> item)
{
dictionay.Add(item.Key, item.Value);
}
public virtual bool Contains(KeyValuePair<TK, TV> item)
{
return dictionay.ContainsKey(item.Key) && dictionay.ContainsValue(item.Value);
}
public virtual void CopyTo(KeyValuePair<TK, TV>[] array, int arrayIndex)
{
}
public virtual int Count
{
get { return dictionay.Count; }
}
public virtual bool Remove(KeyValuePair<TK, TV> item)
{
return false;
}
#endregion
#region IEnumerable<KeyValuePair<TK,TV>> 成员
public virtual IEnumerator<KeyValuePair<TK, TV>> GetEnumerator()
{
return dictionay.GetEnumerator();
}
#endregion
#region IEnumerable 成员
IEnumerator IEnumerable.GetEnumerator()
{
return dictionay.GetEnumerator();
}
#endregion
}
}
这还只是一个集合基类,按照bbsmax的框架,我们需要为“全局模板变量”实体(TemplateVar)创建一个它专有的 “实体集合“类,不用觉得麻烦,它很简单,只需要继承刚才的 ”集合基类“就可以了。
using System;
using System.Collections.Generic;
using System.Text;
using MaxLabs.bbsMax.DataAccess;
using MaxLabs.bbsMax.Enums;
namespace MaxLabs.bbsMax.Entities
{
/// <summary>
/// 全局模板实体类变量集合
/// </summary>
public class TemplateVarDictionary : EntityDictionaryBase<string, TemplateVar>
{
public TemplateVarDictionary()
{
}
/// <summary>
/// 同实体类,根据数据库data对象,封装为集合。
/// </summary>
/// <param name="__readerWrap"></param>
public TemplateVarDictionary(DataReaderWrap __readerWrap)
{
//while每次循环取一行数据,一行数据就是一个实体对象,封装之
while (__readerWrap.Next)
{
//封装一行数据
TemplateVar entity = new TemplateVar(__readerWrap);
//加入集合
base.Add(entity.Hash, entity);
}
}
public TemplateVarDictionary(TemplateVarDictionary __collection)
{
if (__collection == null)
{
return;
}
foreach (var row in __collection)
{
this.Add(row.Key, row.Value);
}
}
/// <summary>
/// 嘿嘿,知道自己写集合类的好处了把,咱可以重写,多自由
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public override TemplateVar this[string key]
{
get
{
//如果根据key在集合内找不到指定的“全局模板变量”,则返回一行默认数据,
//而不是让aspx报错,避免整个aspx页面会崩溃掉
if (!base.ContainsKey(key))
{
return new TemplateVar { Value = string.Format("给定的通用模板变量 {0} 不存在", key) };
}
return base[key];
}
set
{
base[key] = value;
}
}
}
}
实体类 和 实体集合类 都已写好,下面写 抽象类(DAO)。
using MaxLabs.bbsMax.Entities;
//注意命名空间
namespace MaxLabs.bbsMax.DataAccess
{
/// <summary>
/// "全局模板变量"的数据库访问抽象类
/// </summary>
public abstract class TemplateVarDao : DaoBase<TemplateVarDao>
{
/// <summary>
/// 查询
/// </summary>
/// <returns></returns>
public abstract TemplateVarDictionary Select();
/// <summary>
/// 添加
/// </summary>
/// <param name="__hash">模板变量的键</param>
/// <param name="__value">模板变量的值</param>
/// <returns></returns>
public abstract int Insert(string __hash, string __value);
/// <summary>
/// 更新
/// </summary>
/// <param name="__tvid">自增列</param>
/// <param name="__hash"></param>
/// <param name="__value"></param>
/// <returns></returns>
public abstract int Update(int __tvid, string __hash, string __value);
}
}
按照bbsmax的框架,我们需要添加一个额外的 “全局模板变量”缓存类,不要觉得麻烦,其实结构很简单,就是一个静态的集合,一个访问器。
using MaxLabs.bbsMax.Entities;
namespace MaxLabs.bbsMax
{
public class TemplateVarCachePool
{
//string key键/值集合
static TemplateVarDictionary _vars;
/// <summary>
/// 缓存[集合]
/// 一般从数据库数据库查询数据之后,存放到这里
/// </summary>
public static TemplateVarDictionary Vars
{
get { return _vars; }
set { _vars = value; }
}
public void Clear()
{
if (_vars != null)
{
_vars.Clear();
}
}
}
}
可以写逻辑类了
using MaxLabs.bbsMax.Entities;
namespace MaxLabs.bbsMax
{
/// <summary>
/// 全局模板变量[逻辑类]
/// </summary>
public class TemplateVarBO : BOBase<TemplateVarBO>
{
/// <summary>
/// 查询
/// </summary>
/// <returns>可通过string key访问的集合</returns>
public TemplateVarDictionary Select()
{
if (TemplateVarCachePool.Vars != null)
{
return TemplateVarCachePool.Vars;
}
TemplateVarCachePool.Vars = DataAccess.TemplateVarDao.Instance.Select();
return TemplateVarCachePool.Vars;
}
public int Insert(string __hash, string __value)
{
return DataAccess.TemplateVarDao.Instance.Insert(__hash, __value);
}
public int Update(int __tvid, string __hash, string __value)
{
return DataAccess.TemplateVarDao.Instance.Update(__tvid, __hash, __value);
}
}
}
以上类都在[MaxLabs.bbsMax]层中。
实体,实体集合,数据访问抽象,缓存,逻辑,各类已经完成。下面实现“ 数据访问抽象类”的类
在[MaxLabs.bbsMax.DataAccess.SqlServer]层中,实现 [MaxLabs.bbsMax]层中 所有"数据访问抽象类"(DAO)。
using System.Data;
using MaxLabs.bbsMax.Entities;
namespace MaxLabs.bbsMax.DataAccess.SqlServer
{
/// <summary>
/// "全局模板变量"的数据库访问实现类
/// </summary>
public class TemplateVarDao : bbsMax.DataAccess.TemplateVarDao
{
/// <summary>
/// 查询
/// </summary>
/// <returns></returns>
public override TemplateVarDictionary Select()
{
using (SqlQuery query = new SqlQuery())
{
//SQL语句
query.CommandText = "SELECT * FROM [bx_templatevars]";
//SQL语句类型。
query.CommandType = CommandType.Text;
//查!
using (XSqlDataReader reader = query.ExecuteReader())
{
//new出自定义的“模板变量集合”
//封装方法1:
//将数据库reader对象丢过去,完成。
TemplateVarDictionary result = new TemplateVarDictionary(reader);
//封装方法2:
////也可以这样
//while (reader.Next)
//{
// TemplateVar entity = new TemplateVar(reader);
// result.Add(entity.Hash, entity);
//}
return result;
}
}
}
public override int Insert(string __hash, string __value)
{
using (SqlQuery query = new SqlQuery())
{
string sql = "INSERT INTO [bx_templatevars] ([hash],[value]) VALUES (@hash,@value)";
query.CreateParameter<string>("@hash", __hash, SqlDbType.NVarChar, 150);
query.CreateParameter<string>("@value", __value, SqlDbType.NText);
query.CommandText = sql;
return query.ExecuteNonQuery();
}
}
public override int Update(int __tvarid, string __hash, string __value)
{
using (SqlQuery query = new SqlQuery())
{
string sql = "UPDATE [bx_templatevars] SET [hash] = @hash, [value] = @value WHERE [tvarid] = @tvarid";
query.CreateParameter<int>("@tvarid", __tvarid, SqlDbType.Int);
query.CreateParameter<string>("@hash", __hash, SqlDbType.NVarChar, 150);
query.CreateParameter<string>("@value", __value, SqlDbType.NText);
query.CommandText = sql;
return query.ExecuteNonQuery();
}
}
}
}
添加一个 "抽象类实现类" 到 "抽象类(DAO)" 的实例化关系映射。
同样在[MaxLabs.bbsMax.DataAccess.SqlServer]层中:
\InternalCode\DataProvider 类下的
public T Create<T>() where T : DaoBase<T>
在这个“T Create<T>”方法的合适的位置("throw new Exception" 之上)添加如下代码:
if (typeof(T)==typeof(DataAccess.TemplateVarDao))
{
return new TemplateVarDao() as T;
}
在页面基类添加变量访问器(第7步)。
在 [MaxLabs.bbsMax.Web]层的 _codes\_pagebase\BbsPageBase 页面基类下 ,添加如下代码
public TemplateVarDictionary Vars
{
get { return TemplateVarBO.Instance.Select(); }
}
修改论坛模板,添加如下代码:
<div id="">这是从数据库取到的vars["indexsay"]变量: $vars["indexsay"]</div>