您的位置:首页 > 编程语言

微型项目实践(6):Business层代码分析——实体类的生成策略

2008-05-09 20:53 483 查看
上一篇中,我们分析了实体类的基类Entity,这一篇中,我们就分析一下基于该类的实体类。







每一个实体类都会有两个文件组成,我们以BlogClass为例,该类包含两个文件:BlogClass.cs和BlogClass.designer.cs,这非常类似VS自己生成的代码,更方便的是,VS还会自动把这两个文件折叠起来,如图。

这两个文件中,BlogClass.designer.cs包含所有的生成代码:成员、属性等,而BlogClass.cs则只包含一个类的定义,供我们填写代码使用。

BlogClass.designer.cs的代码如下。

1:usingSystem;
2:usingSystem.Collections.Generic;
3:usingSystem.Data.Linq;
4:usingSystem.Linq;
5:usingSystem.Text;
6:
7:usingDongBlog.Common;
8:
9:namespaceDongBlog.Business.Blogs
10:{
11:///<summary>
12:///日志分类
13:///</summary>
14:publicpartialclassBlogClass
15:{
16:#regionID和时间戳
17:
18:privateint_ID=NEW_ENTITY_ID;
19:privatebyte[]_TimeStamp=newbyte[]{};
20:
21:///<summary>
22:///取得ID
23:///</summary>
24:publicoverrideintID
25:{
26:get{return_ID;}
27:}
28:///<summary>
29:///取得时间戳
30:///</summary>
31:publicoverridebyte[]TimeStamp
32:{
33:get{return_TimeStamp;}
34:}
35:
36:#endregion
37:
38:#region成员
39:
40:privatestring_Name;
41:privatestring_Description;
42:
43:#endregion
44:
45:#region属性
46:
47:///<summary>
48:///取得或设置名称
49:///</summary>
50:publicstringName
51:{
52:get{return_Name;}
53:set{_Name=value;}
54:}
55:///<summary>
56:///取得或设置描述
57:///</summary>
58:publicstringDescription
59:{
60:get{return_Description;}
61:set{_Description=value;}
62:}
63:
64:#endregion
65:}
66:}

.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}

从代码里可以看到,完全就是对实体XML的翻译,需要特别指出的是,其中实现了Entity定义的ID和TimeStamp这两个抽象属性。

BlogClass.cs的代码如下:

1:usingSystem;
2:usingSystem.Collections.Generic;
3:usingSystem.Data.Linq;
4:usingSystem.Linq;
5:usingSystem.Text;
6:
7:usingDongBlog.Common;
8:
9:namespaceDongBlog.Business.Blogs
10:{
11:///<summary>
12:///日志分类
13:///</summary>
14:publicpartialclassBlogClass:Entity<BlogClass>
15:{
16:}
17:
18:///<summary>
19:///日志分类的业务外观
20:///</summary>
21:publicstaticclassBlogClassExtension
22:{
23:}
24:}

呃……这个更简单了,完全就是个空的。因为它的用处就是让我们填写自己的代码,现在假设我们有这么一个功能“设置日志分类名称时,如果分类的描述为空,则将分类的描述设置为其名称”,那么我们可以这么干:从BlogClass.desinger.cs文件中,将Name属性的定义Ctrl+X,Ctrl+V过来,然后改改,修改后的代码如下:

1:usingSystem;
2:usingSystem.Collections.Generic;
3:usingSystem.Data.Linq;
4:usingSystem.Linq;
5:usingSystem.Text;
6:
7:usingDongBlog.Common;
8:
9:namespaceDongBlog.Business.Blogs
10:{
11:///<summary>
12:///日志分类
13:///</summary>
14:publicpartialclassBlogClass:Entity<BlogClass>
15:{
16:///<summary>
17:///取得或设置名称
18:///</summary>
19:publicstringName
20:{
21:get{return_Name;}
22:set
23:{
24:_Name=value;
25:
26:if(string.IsNullOrEmpty(_Description))
27:_Description=value;
28:}
29:}
30:}
31:
32:///<summary>
33:///日志分类的业务外观
34:///</summary>
35:publicstaticclassBlogClassExtension
36:{
37:}
38:}

这个代码很好理解,值得一提的是,当描述实体的XML修改后,重新生成实体代码时,代码生成器会判断BlogClass.cs中是否包含了Name属性,如果包含了该属性,则在BlogClass.designer.cs中,就不会再生成了。这是自己写代码生成而不用通用代码生成器的好处——我的地盘我做主。:)

另外一个和实体相关的类是Extension类,顾名思义,该类包含的都是对已有类型的扩展方法,利用C#3.0的扩展方法,可以写出非常优雅的代码。例如,我们需要查询某一个分类的所有Blog,给出的是该分类的ID,我们就可以在BlogExtension类中这么写(代码位于\DongBlog.Business\Blogs\Blog.cs):

1:///<summary>
2:///日志的业务外观
3:///</summary>
4:publicstaticclassBlogExtension
5:{
6:///<summary>
7:///根据日志分类取得日志
8:///</summary>
9:///<paramname="query">日志查询</param>
10:///<paramname="blogClassID">日志分类ID</param>
11:///<returns>该分类下的日志</returns>
12:publicstaticList<Blog>GetBlogsByClassID(thisIQueryable<Blog>query,intblogClassID)
13:{
14:if(query==null)
15:thrownewArgumentNullException("query");
16:
17:returnquery
18:.Where(b=>b.BlogClassID==blogClassID)
19:.OrderByDescending(b=>b.UpdateDateTime)
20:.ToList();
21:}
22:}

上面的查询方法使用Linq实现的,我们还顺手做了一个根据更新时间的排序。有了这个方法,我们以后就可以用这样的方式取得某一个分类的Blog:database.GetDataAccess<Blog>().GetBlogByClassID(1);该方式以后还会进一步简化为:database.Blogs.GetBlogByClassID(1)。

最后说明一点,以上代码都是可以测试的,因为我们所有的方法都是使用接口作为参数的,所以我们可以用脚手架(Mock类)伪实现相应的接口,以便对不同输入和环境下的代码进行自动化测试,具体方法就不展开了。

下一篇文章我们将分析数据访问的设计与实现。

代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: