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

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

2008-05-10 13:15 459 查看
上一篇中,我们分析了实体类的基类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类)伪实现相应的接口,以便对不同输入和环境下的代码进行自动化测试,具体方法就不展开了。

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

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