关闭页面特效

Kooboo CMS 之TextContent详解

 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 0; } 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) == 0)) { 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 0; } set { base["OriginalUpdateTimes"] = value; } } public int OriginalLastestVisitedVersionId { get { if (this.ContainsKey("OriginalLastestVisitedVersionId") && base["OriginalLastestVisitedVersionId"] != null) { return Convert.ToInt32(base["OriginalLastestVisitedVersionId"]); } return 0; } set { base["OriginalLastestVisitedVersionId"] = value; } } #endregion } }
View Code

大家有没有发现,代码里面没有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 }

 


__EOF__

作  者ღKawaii
出  处https://www.cnblogs.com/kmsfan/p/kooboo_cms_textcontent_Introduce.html
关于博主:一个普通的小码农,为了梦想奋斗
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!

posted @   yangliwen  阅读(854)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
0
0
关注
跳至底部
document.getElementById("homeTopTitle").innerText="ღKawaii";
点击右上角即可分享
微信分享提示