TextCotent 在Kooboo.CMS.Content下面,在View中有使用到这个模型层。

  TextContent继承了ContentBase,而ContentBase是由2个部分类组成的,一个是内容对象基类的子类,另一个是实现了持久化.那。。。我们该如何去理解呢,这里我用PS画一幅图大家就懂了。TextContent有3个构造函数,其中这2个构造函数都和基类(ContentBase)有关系。这3个构造函数分别如下:

        /// <summary>
/// Initializes a new instance of the <see cref="TextContent"/> class.
/// </summary>
/// <param name="dictionary">The dictionary.</param>
public TextContent(IDictionary<string, object> dictionary)
: base(dictionary)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TextContent"/> class.
/// </summary>
public TextContent()
: base()
{
this.Id = string.Empty;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextContent"/> class.
/// </summary>
/// <param name="repository">The repository.</param>
/// <param name="schemaName">Name of the schema.</param>
/// <param name="folderName">Name of the folder.</param>
public TextContent(string repository, string schemaName, string folderName)
: base(repository, folderName)
{
this.Id = string.Empty;
this.SchemaName = schemaName;
}

  大家也许会疑惑这个TextContent有什么用处,看看视图里面的ViewBag.XXX你就明白了,其实ViewBag.XXX得到的是一个弱类型,可以强制转换成TextContent,为什么我这么自信它可以转换为TextContent呢?因为其实在数据库里建立的这张表和TextContent是一一对应的,字段的名称都是相同的。

下面的是TextContent的全部代码,大家有兴趣的可以对比一下,都是一样的。

#region License
//
// Copyright (c) 2013, Kooboo team
//
// Licensed under the BSD License
// See the file LICENSE.txt for details.
//
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using Kooboo.CMS.Common.Persistence.Non_Relational; namespace Kooboo.CMS.Content.Models
{
/// <summary>
/// 文本内容
/// </summary>
public class TextContent : ContentBase
{
/// <summary>
/// Initializes a new instance of the <see cref="TextContent"/> class.
/// </summary>
/// <param name="dictionary">The dictionary.</param>
public TextContent(IDictionary<string, object> dictionary)
: base(dictionary)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="TextContent"/> class.
/// </summary>
public TextContent()
: base()
{
this.Id = string.Empty;
}
/// <summary>
/// Initializes a new instance of the <see cref="TextContent"/> class.
/// </summary>
/// <param name="repository">The repository.</param>
/// <param name="schemaName">Name of the schema.</param>
/// <param name="folderName">Name of the folder.</param>
public TextContent(string repository, string schemaName, string folderName)
: base(repository, folderName)
{
this.Id = string.Empty;
this.SchemaName = schemaName;
} /// <summary>
/// 内容对应的Schema(Content type)
/// </summary>
/// <value>
/// The name of the schema.
/// </value>
public string SchemaName
{
get
{
if (this.ContainsKey("SchemaName") && base["SchemaName"] != null)
{
return base["SchemaName"].ToString();
}
return null;
}
set
{
base["SchemaName"] = value;
}
} /// <summary>
/// 内嵌内容的父目录
/// </summary>
public string ParentFolder
{
get
{
if (this.ContainsKey("ParentFolder") && base["ParentFolder"] != null)
{
return base["ParentFolder"].ToString();
}
return null;
}
set
{
base["ParentFolder"] = value;
}
}
/// <summary>
///内嵌内容的父内容的UUID
/// </summary>
public string ParentUUID
{
get
{
if (this.ContainsKey("ParentUUID") && base["ParentUUID"] != null)
{
return base["ParentUUID"].ToString();
}
return null;
}
set
{
base["ParentUUID"] = value;
}
} /// <summary>
/// Gets the type of the content.
/// </summary>
/// <value>
/// The type of the content.
/// </value>
public override ContentType ContentType
{
get
{
return ContentType.Text;
}
}
/// <summary>
/// 内容被广播过来的源UUID
/// </summary>
public string OriginalUUID
{
get
{
if (this.ContainsKey("OriginalUUID") && base["OriginalUUID"] != null)
{
return base["OriginalUUID"].ToString();
}
return null;
}
set
{
base["OriginalUUID"] = value;
}
}
/// <summary>
/// 内容被广播过来的源仓库
/// </summary>
public string OriginalRepository
{
get
{
if (this.ContainsKey("OriginalRepository") && base["OriginalRepository"] != null)
{
return base["OriginalRepository"].ToString();
}
return null;
}
set
{
base["OriginalRepository"] = value;
}
}
/// <summary>
/// 内容被广播过来的源目录
/// </summary>
public string OriginalFolder
{
get
{
if (this.ContainsKey("OriginalFolder") && base["OriginalFolder"] != null)
{
return base["OriginalFolder"].ToString();
}
return null;
}
set
{
base["OriginalFolder"] = value;
}
}
/// <summary>
///内容被广播过来后是否本地化了
/// </summary>
public bool? IsLocalized
{
get
{
if (this.ContainsKey("IsLocalized") && base["IsLocalized"] != null)
{
return (bool)base["IsLocalized"];
}
return true;
}
set
{
base["IsLocalized"] = value;
}
} /// <summary>
/// 内容的排序顺序
/// </summary>
public int Sequence
{
get
{
if (this.ContainsKey("Sequence") && base["Sequence"] != null)
{
return Convert.ToInt32(base["Sequence"]);
}
return ;
}
set
{
base["Sequence"] = value;
}
} /// <summary>
/// 内容是否有附件
/// </summary>
/// <returns>
/// <c>true</c> if this instance has attachment; otherwise, <c>false</c>.
/// </returns>
public bool HasAttachment()
{
var schema = this.GetSchema();
foreach (var column in schema.AsActual().Columns.Where(it => string.Compare(it.ControlType, "File", true) == ))
{
var value = this[column.Name];
if (value != null && !string.IsNullOrEmpty(value.ToString()))
{
return true;
}
}
return false;
} /// <summary>
/// 保存时,要存储的附件
/// </summary>
public IEnumerable<ContentFile> ContentFiles { get; set; } /// <summary>
/// Called when [saving].
/// </summary>
protected override void OnSaving()
{
base.OnSaving();
this.UserKey = UserKeyGenerator.DefaultGenerator.Generate(this);
} #region override object
public override bool Equals(object obj)
{
if (!(obj is ContentBase))
{
return false;
}
var c = (ContentBase)obj;
if (this.UUID.EqualsOrNullEmpty(c.UUID, StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
#endregion public bool ___EnableVersion___
{
get
{
if (this.ContainsKey("___EnableVersion___") && base["___EnableVersion___"] != null)
{
return (bool)base["___EnableVersion___"];
}
return true;
}
set
{
base["___EnableVersion___"] = value;
}
} #region MoreOptionsOnBroadcasting
public int OriginalUpdateTimes
{
get
{
if (this.ContainsKey("OriginalUpdateTimes") && base["OriginalUpdateTimes"] != null)
{
return (int)(base["OriginalUpdateTimes"]);
}
return ;
}
set
{
base["OriginalUpdateTimes"] = value;
}
}
public int OriginalLastestVisitedVersionId
{
get
{
if (this.ContainsKey("OriginalLastestVisitedVersionId") && base["OriginalLastestVisitedVersionId"] != null)
{
return Convert.ToInt32(base["OriginalLastestVisitedVersionId"]);
}
return ;
}
set
{
base["OriginalLastestVisitedVersionId"] = value;
}
}
#endregion
}
}

大家有没有发现,代码里面没有Title,Photo和Description这3个字段,那么这3个字段又是从哪里来的呢?看下面的图,原来是我们在内容类型里面自定义的。

我们可以查看一下这3个字段在数据库中的类型:

这里证明了一点,至少证明了一点,Kooboo CMS在对于String 类型的字符串,只要你没有设置长度的话,默认是到最长,这里补充一点,长度在Kooboo CMS中是可以去设置的,在这里设置。

  好了,下面来讲解一下各个字段的用途。

  • UUID:类似于Guid码,Kooboo CMS自己定义的一套生成编码的规则方法所生成的不定字符串。
  • Repository:仓库,一个网站就是一个仓库,你可以把仓库理解为网站的名称,但是不是显示名称,这个名称是建立了就不可修改的。
  • FolderName:文件夹名称。
  • UserKey:下面的是这么解释的。。。。。这个主要是用在条件过滤的时候
        /// <summary>
/// 根据Summary字段生成的一个友好的唯一主键值,一般用于在URL中传递。
/// </summary>
public string UserKey
{
get
{
if (this.ContainsKey("UserKey") && base["UserKey"] != null)
{
return base["UserKey"] == null ? "" : base["UserKey"].ToString();
}
return null;
}
set
{
base["UserKey"] = value;
}
}

下面的图将会为你解释UserKey的作用,当然前提是你需要一个Summary 概述字段,Summary字段是自己去勾选的,在CMS的后台里面。

而配置UserKey的地方在View里面的数据查询可以配置。

看到了吗,其实这里可以进行内容过滤,如果是UserKey的话,那么就是下面这么一种写法。

UserKey=={UserKey} 这里的{UserKey}就是一个不定的参数,我个人感觉类似于string.Format()里面的{0}{1}这种形式的参数表示法。

我们再来想一下一个问题,为什么ContentBase要继承DynamicDictionary呢?我们先来看一下DynamicDictionary的结构,我这里为了简化只放出属性。

  public class DynamicDictionary : DynamicObject, IDictionary<string, object>
{
#region Fields
IDictionary<string, object> dictionary;
#endregion #region Properties
/// <summary>
/// Gets the count.
/// </summary>
/// <value>
/// The count.
/// </value>
int ICollection<KeyValuePair<string, object>>.Count
{
get
{
return dictionary.Count;
}
}
#endregion }

  其实说白了就是字典的扩展嘛。其实说简单一点,就是基类对象里面如果有UserKey的话,那么就会用get方法得到其值其余的就不多说了,大多是描述字段。

这里最后在介绍一下ContentBase对于IPersistable的支持。

本来想说一下的,但是太晚了,而且这个太难,做个记号,以后懂了再讲解。

    /// <summary>
/// ContentBase对IPersistable的实现
/// </summary>
public partial class ContentBase : IPersistable
{
/// <summary>
/// The content integrate id composite of Repository, FolderName and UUID. example: Repository#FolderName#UUID
/// </summary>
public string IntegrateId
{
get
{
return new ContentIntegrateId(this).ToString();
}
}
#region IPersistable Members private bool isDummy = true;
bool IPersistable.IsDummy
{
get { return isDummy; }
} void IPersistable.Init(IPersistable source)
{
isDummy = false;
} void IPersistable.OnSaved()
{
isDummy = false;
} void IPersistable.OnSaving()
{
OnSaving();
}
protected virtual void OnSaving()
{
if (string.IsNullOrEmpty(this.UUID))
{
this.UUID = UUIDGenerator.DefaultGenerator.Generate(this);
}
} #endregion }

Kooboo CMS 之TextContent详解的更多相关文章

  1. Kooboo CMS - Html.FrontHtml[Helper.cs] 各个方法详解

    下面罗列了方法详解,每一个方法一篇文章. Kooboo CMS - @Html.FrontHtml().HtmlTitle() 详解 Kooboo CMS - Html.FrontHtml.Posit ...

  2. Kooboo CMS - @Html.FrontHtml().Meta()详解。

    下面是代码: public virtual IHtmlString Meta() { AggregateHtmlString htmlStrings = new AggregateHtmlString ...

  3. Kooboo CMS - Html.FrontHtml.Position 详解

    DataContract 数据契约 http://www.cnblogs.com/Gavinzhao/archive/2010/06/01/1748736.html https://msdn.micr ...

  4. GC:并行回收CMS详解

    CMS详解 https://www.cnblogs.com/ggjucheng/p/3977612.html CMS默认不回收Perm, 需要加参数 +CMSPermGenSweepingEnable ...

  5. NopCommerce源码架构详解--初识高性能的开源商城系统cms

    很多人都说通过阅读.学习大神们高质量的代码是提高自己技术能力最快的方式之一.我觉得通过阅读NopCommerce的源码,可以从中学习很多企业系统.软件开发的规范和一些新的技术.技巧,可以快速地提高我们 ...

  6. Kooboo CMS技术文档之三:切换数据存储方式

    切换数据存储方式包括以下几种: 将文本内容存储在SqlServer.MySQL.MongoDB等数据库中 将站点配置信息存储在数据库中 将后台用户信息存储在数据库中 将会员信息存储在数据库中 将图片. ...

  7. Kooboo CMS技术文档之二:Kooboo CMS的安装步骤

    在IIS上安装Kooboo CMS Kooboo CMS安装之后 安装的常见问题 1. 在IIS上安装Kooboo CMS Kooboo CMS部署到正式环境相当简单,安装过程是一个普通MVC站点在I ...

  8. 详解Java GC的工作原理+Minor GC、FullGC

    详解Java GC的工作原理+Minor GC.FullGC 引用地址:http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html J ...

  9. 服务器.htaccess 详解以及 .htaccess 参数说明(转载)

    htaccess文件(或者”分布式配置文件”)提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录.作为用户,所能使用的命令受到限 ...

随机推荐

  1. *CF2.D(哥德巴赫猜想)

    D. Taxes time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  2. java并发编程(五)正确使用volatile

    转载请注明出处:     volatile用处说明     在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...

  3. poj3187-Backward Digit Sums(枚举全排列)

    一,题意: 输入n,sum,求1~n的数,如何排列之后,相邻两列相加,直到得出最后的结果等于sum,输出1~n的排列(杨辉三角)  3 1 2 4 //1~n 全排列中的一个排列  4 3 6  7 ...

  4. 初试Office 365企业版E3

    Microsoft Office 365 团队给了所有现任的MVP 12个月的微软 Office 365 企业 E3 订阅,今天激活账号并试用了一下,发现非常强大,本文简要介绍下Office 365 ...

  5. quick-cocos2d-x 2.2.3 rc版本中 crypto.md5file() 的C++实现在ANDROID上有BUG

    原来的版本是用fopen打开文件的,如果要从ANDROID的APK中取文件,直接就洗白了修改如下 void CCCrypto::MD5File(const char* path, unsigned c ...

  6. 关于分工的思考 (Thoughts on Division of Labor)

    Did you ever have the feeling that adding people doesn't help in software development? Did you ever ...

  7. 拓展 Android 原生 CountDownTimer 倒计时

    拓展 Android 原生 CountDownTimer 倒计时 [TOC] CountDownTimer 在系统的CountDownTimer上进行的修改,主要是拓展了功能,当然也保留了系统默认的模 ...

  8. Atitit webservice的发现机制 discover机制

    Atitit webservice的发现机制 discover机制 1.1. Ws disconvert 的组播地址和端口就是37021 1.2. Ws disconvert的发现机制建立在udp组播 ...

  9. 我的SQL总结---未完待续

    我的SQL总结---未完待续 版权声明:本文为博主原创文章,未经博主允许不得转载. 总结: 主要的SQL 语句: 数据操作(select, insert, delete, update) 访问控制(g ...

  10. Angular $watch

    如果想在某个属性发生变化的时候执行某些操作,那么scope.$watch是最佳选择 https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$w ...