研究一下模型类,总共有6个类,它们都表示所包含的内容。
1. AbstractPage
1: [WithEditableTitle, WithEditableName]
<!--CRLF-->
2: public abstract class AbstractPage : ContentItem, INode<!--CRLF-->
3: {
<!--CRLF-->
4: public string PreviewUrl<!--CRLF-->
5: {
<!--CRLF-->
6: get { return Url; }<!--CRLF-->
7: }
<!--CRLF-->
8: }
<!--CRLF-->
这个抽象类代表所有将以页面显示的内容项。WithEditableTitle特性让此类的Title属性可被编辑,WithEditableName让此类的Name属性可被编辑。定义的只读属性PreviewUrl,直接返回Url值,似乎没有什么用。
2. ContentPage
1: [Definition("Content Page", Installer = N2.Installation.InstallerHint.PreferredStartPage)]<!--CRLF-->
2: public class ContentPage : AbstractPage<!--CRLF-->
3: {
<!--CRLF-->
4: [EditableFreeTextArea("Text", 100)]<!--CRLF-->
5: public virtual string Text<!--CRLF-->
6: {
<!--CRLF-->
7: get { return (string)(GetDetail("Text") ?? string.Empty); }<!--CRLF-->
8: set { SetDetail("Text", value, string.Empty); }<!--CRLF-->
9: }
<!--CRLF-->
10: }
<!--CRLF-->
这个类表示有文字内容的内容项,也就是它拥有内容了,这是通过虚拟的Text属性来进行获取和设置的。Definition特性用于为ContentPage指定一些特殊的设置,第一个参数是它的标题(显示在N2管理界面中,当新建和编辑页面的时候可以看到),第二个是设置属性Installer,它让N2在安装此网站时能让ContentPage也作为起始页进行选择(在安装的第2步可以看到)。最好不要用这个特性,而是用更准确的PageDefinition代替。ContentPage类定义的Text属性上的EditableFreeTextArea特性是表示Text属性将可以被N2用一个富文本编辑器编辑,get和set方法其实可以写的更省一些。
3. NewsPage
1: [Definition("News")]<!--CRLF-->
2: [RestrictParents(typeof(NewsContainer))]<!--CRLF-->
3: public class NewsPage : AbstractPage<!--CRLF-->
4: {
<!--CRLF-->
5: public NewsPage()<!--CRLF-->
6: {
<!--CRLF-->
7: Visible = false;<!--CRLF-->
8: }
<!--CRLF-->
9:
<!--CRLF-->
10: [EditableFreeTextArea("Text", 100)]<!--CRLF-->
11: public virtual string Text<!--CRLF-->
12: {
<!--CRLF-->
13: get { return (string)(GetDetail("Text") ?? string.Empty); }<!--CRLF-->
14: set { SetDetail("Text", value, string.Empty); }<!--CRLF-->
15: }
<!--CRLF-->
16:
<!--CRLF-->
17: public virtual IEnumerable GetComments()<!--CRLF-->
18: {
<!--CRLF-->
19: foreach (ContentItem item in GetChildren())<!--CRLF-->
20: {
<!--CRLF-->
21: if (item is CommentItem)<!--CRLF-->
22: {
<!--CRLF-->
23: yield return item as CommentItem;<!--CRLF-->
24: }
<!--CRLF-->
25: }
<!--CRLF-->
26: }
<!--CRLF-->
27: }
<!--CRLF-->
NewsPage表示新闻内容,而且它通过RestrictParents限制其父结点只能是NewsContainer类。它的构造函数中把Visible属性设置为false,查看文档知道这可以让新闻页面不显示在站点地图中,当然也可以让它不显示在导航中。另外新闻可以有评论,所以GetComments方法返回所有评论,这也说明NewsPage是评论的父结点。
4. NewsContainer
1: [Definition("News Collection")]<!--CRLF-->
2: public class NewsContainer : AbstractPage<!--CRLF-->
3: {
<!--CRLF-->
4: public virtual IEnumerable GetNews()<!--CRLF-->
5: {
<!--CRLF-->
6: return GetChildren(new AccessFilter(), new TypeFilter(typeof (NewsPage))).Cast();<!--CRLF-->
7: }
<!--CRLF-->
8: }
<!--CRLF-->
新闻容器类,它的作用就是列出所有的新闻,这个工作由GetNews方法来实现。
5. CommentItem
1: [Definition("Comment")]<!--CRLF-->
2: [RestrictParents(typeof(NewsPage))]<!--CRLF-->
3: public class CommentItem : AbstractPage<!--CRLF-->
4: {
<!--CRLF-->
5: public override bool IsPage<!--CRLF-->
6: {
<!--CRLF-->
7: get { return false; }<!--CRLF-->
8: }
<!--CRLF-->
9:
<!--CRLF-->
10: public override string IconUrl<!--CRLF-->
11: {
<!--CRLF-->
12: get { return "~/Content/comment.png"; }<!--CRLF-->
13: }
<!--CRLF-->
14:
<!--CRLF-->
15: [EditableFreeTextArea("Text", 100)]<!--CRLF-->
16: public virtual string Text<!--CRLF-->
17: {
<!--CRLF-->
18: get { return (string)(GetDetail("Text") ?? string.Empty); }<!--CRLF-->
19: set { SetDetail("Text", value, string.Empty); }<!--CRLF-->
20: }
<!--CRLF-->
21: }
<!--CRLF-->
表示新闻的评论,所以有RestrictParents特性进行约束。另外有趣的是因为它不应该显示到单独的页面中,所以重写了IsPage属性,让其总是返回false。其他的属性就不用解释了。
6. TextPart
1: [PartDefinition("TextPart")]<!--CRLF-->
2: public class TextPart : ContentItem<!--CRLF-->
3: {
<!--CRLF-->
4: [EditableFreeTextArea("Text", 100)]<!--CRLF-->
5: public virtual string Text<!--CRLF-->
6: {
<!--CRLF-->
7: get { return (string)(GetDetail("Text") ?? string.Empty); }<!--CRLF-->
8: set { SetDetail("Text", value, string.Empty); }<!--CRLF-->
9: }
<!--CRLF-->
10: }
<!--CRLF-->
这个类不是从抽象的AbstractPage派生的,而是直接派生自ContentItem类,而且使用了PartDefinition特性进行修饰,这种模型对象通常会通过ASCX模板进行呈现,而不是页面模板(ASPX),说明它应该显示在页面中的某个部位,类似于WebForm中的用户控件,这样可以在不同的页面中重用。具体使用还没有研究过。