想一想还挺有意思的,从内容代码混杂,脚本横行的asp时代,到“CodeBehind” 的服务控件端编程时代,再到现在各种丰富和强大js库的兴起,各种眼花缭乱的js插件,“胖客户端”的流行,不得不感慨一下,怎么玩着玩着又玩回去了。不过这种“回去”不是倒退,而是顺应发展趋势,同时也是重拾本源,毕竟所有web呈现和控制都是html+css+js【当然其中要排除flash、Silverlight这些“异类”】。相信不久的将来Html5会使前端应用带来巨大的变化。

  不废话了,从本篇开始进入正题,一步步的介绍Smart UI开发框架的使用。

  首先,Smart UI与目前大多数“胖客户端”应用【半服务端+半前端】有所不同,所有UI层全部都是htm+js实现,不存在服务端内容。因此开发模式会传统的不一样,而且对基础技能的要求(对比asp.net)也会高些。只有比较好的掌握了html、css、js、jquery、json这些知识,才能充分发挥纯前端开发的强大优势。

  本篇以一个新闻增删改查的例子大概的说明一下Smart UI的开发流程:

  • 第一步,数据库设计

  表:News

  N_ID 【int】:主键自增id

  N_Title 【nvarchar(50)】: 新闻标题

  N_Centent【nvarchar(1000)】: 新闻内容

  N_Date【Datetime】: 发布时间

 

  •  第二步,创建业务数据类BRNews

  首先将数据库生成实体文件,【工具在NBearLite.QueryColumnsGenerator项目生成的exe文件】,然后在放到Bll层中,实例在Demo/Modal/目录下。实体列的访问namespace为:StructModals.

  然后在Bll层创建业务实现类BRNews,实例在Demo/BR目录,内容如下:

   

public class BRNews
{
/// <summary>
/// 执行Function方法
/// </summary>
/// <param name="fnCode">功能编号</param>
/// <param name="postContent">post的数据</param>
/// <param name="error">自定义返回错误信息</param>
/// <returns>ReponseData</returns>
public static object RunFunction(string fnCode, string postContent, ref string error)
{
object objReponseData = null;
switch (fnCode)
{
case "fn_ns01":
objReponseData
= SelectNews(postContent);
break;
case "fn_ns02":
objReponseData
= SaveNews(postContent);
break;
case "fn_ng03":
objReponseData
= GetNewsByID(postContent);
break;
case "fn_nd04":
objReponseData
= DelNewsByIDs(postContent);
break;
}
return objReponseData;
}

/// <summary>
/// 查询方法
/// </summary>
/// <param name="postContent">查询参数</param>
/// <returns>返回列表查询对象(ResponseListData)</returns>
public static object SelectNews(string postContent)
{
UISearchHelper ma
= new UISearchHelper(StructModals.News, postContent);//创建查询类
ma.Select();
if (ma.HasCondition)//判断是否有查询条件
ma.Where(StructModals.News.N_Title, EConditionOperate.Contains);//添加查询项
return ma.GetResponseListData();
}

/// <summary>
/// 保存方法
/// </summary>
/// <param name="postContent">更新参数</param>
/// <returns>是否保存成功(bool)</returns>
public static object SaveNews(string postContent)
{
UIUpdateHelper saveHelper
= new UIUpdateHelper(StructModals.News, postContent);//创建更新类
if (saveHelper.HasValues)//判断是否有更新参数
return saveHelper.AddUpdateColumn(StructModals.News.N_Title, StructModals.News.N_Centent)//自动获取值的更新字段
.AddUpdateColumn(StructModals.News.N_Date, DateTime.Now)//手动设置值更新字段
.Save();//保存方法,会自动判断是否有主键,从而进行insert或是update操作

return false;
}

/// <summary>
/// 根据ID获取内容的方法
/// </summary>
/// <param name="postContent">ID值</param>
/// <returns>单个对象(DataTable)</returns>
public static object GetNewsByID(string postContent)
{
return DBHelper.GetOneDataByID(StructModals.News, postContent);//根据ID获取单条数据
}

/// <summary>
/// 根据ID串批量删除的方法
/// </summary>
/// <param name="postContent">ID串</param>
/// <returns>是否删除成功(bool)</returns>
public static object DelNewsByIDs(string postContent)
{
if (!string.IsNullOrEmpty(postContent))
return DBHelper.DeleteByIDs(StructModals.News, postContent) > 0;//根据主键id串批量删除方法,有事务方法重载
return false;
}
}

 

  BRNews类中,所有方法都为静态,返回参数都为object,其中RunFunction方面则是根据前台传递fncode匹配各个方法,case的每个对象都对应着一个方法,所有方法的参数都一样,一个postData(前台传递的数据),一个error(可选参数,自定义错误)

  其他四个方法,分别对应着增删改差四个功能,除了列表翻页的查询是返回ResponseListData固定格式外,其他方法的返回值可以为任何类型。

  在编写BR类时,大多数情况,开发人员不用关心前台Post过来的数据,通过实例化UISearchHelper【查询帮助类】和UIUpdateHelper【更新帮助类】,开发人员只需要关心查询那些字段,条件是什么,更新那些字段,帮助类会自动的解析和匹配数据。

  • 第三步,注册BRNews类

  完成BRNews后,还需要将其注册到功能适配器FnAdapter类中【Smart UI按模块划分目录,每个模块下的目录都存在一个FnAdapter,实例中是Demo/FnAdapter.cs】,FnAdapter内容如下:

 

public class FnAdapter_Demo
{
public static object RunFuntion(string BRName, PostData postData, ref string error)
{
switch (BRName)
{
case "BRNews":
return BRNews.RunFunction(postData.No, postData.Body, ref error);
case "BRUsers":
return BRUsers.RunFunction(postData.No, postData.Body, ref error);
case "BRProduct":
return BRProduct.RunFunction(postData.No, postData.Body, ref error);
case "BRQuestion":
return BRQuestion.RunFunction(postData.No, postData.Body, ref error);
default:
return null;
}
}
}

 

  FnAdapter中只有一个RunFunction方法,UIHandle下的统一数据接口PostHandle会调用该方法。每个FnAdapter都需要注册到PostHandle中【当然也不是必须的,可以略过,直接通过BR类与PostHandle对应,不过不推荐这样使用,因为当BR类比较多时,通过FnAdapter多加一次检索性能上会提很多,而且也会更加容易维护和管理】。

PostHandle类:

public class PostHandle : PostHttpHandler
{
protected override object GetResponseData(PostData postData, FnCode fncode, ref string error)
{
return RunFuntion(postData, fncode, ref error); ;
}

public static object RunFuntion(PostData postData, FnCode fncode, ref string error)
{
switch (fncode.Module)
{
case "UIDemo":
return FnAdapter_Demo.RunFuntion(fncode.ClassName, postData, ref error);
case "SmartUI":
return FnAdapter.RunFuntion(fncode.ClassName, postData, ref error);
default:
return null;
}
}

}

 

PostHandle类继承抽象类PostHttpHandler,重写GetResponseData方法,传入解析过的前台Post过来的数据,返回请求的数据。各个模块的FnAdapter配置在RunFunction方法中。

 

【注:在整个后台编码中没有用任何接口去进行约束,在此我考虑的是相关的内容结构相对比较简单,为了所有业务方法都能static化,所以没有进行约束。另外,关于配置,如果想更加简洁还有一种方案,在UI层配置fncode的时候,加入BLL的dll信息,使用反射匹配每一个后台方法,这样就只需要在一个位置配置,不过性能的代价比较高,所以没有采用。】

 

 至此,所有后台内容完成,接下来就到重点部分 — 前台功能实现,今天电脑死了两次,写了两遍都没保存,郁闷了。唉,没心情继续了,况且前台的内容比较多,等明天在继续。

  

 posted on 2010-12-09 23:27  Roy Zhang  阅读(8082)  评论(35编辑  收藏  举报