使用插件开发自定义扩展时,使用 IInstallablePlugin 接口和 UI 自动化 API 在安装扩展时安装 UI 组件通常更有效的。
什么是 UI 自动化 API
UI 自动化 API 是 一组 API,可通过进程 API 供给插件,以实现 UI 组件的自动调整。具体而言,它包括以下服务和常量:
Services
ContentWidgets
启用/禁用小组件、识别其他 UI 自动化 API 的小组件、转换小组件以及自动升级小组件(请参见管理小组件源和分发)。
FactoryDefaultScriptedContentWidgetProviderFiles
添加/更新、删除和检测出厂默认小组件提供程序源文件和附件,来安装与出厂默认小组件提供程序(IScriptedContentWidgetFactoryDefaultProvider 插件)关联的文件。有关部署出厂默认小组件的推荐方法,请参阅管理小组件源和分发。
ThemeFiles
添加/更新和检测嵌入的主题文件。
ThemeFooterContentWidgets
列出、插入、替换和删除主题页脚中的小组件。
ThemeFooters
添加、编辑、删除和检测主题页脚。
ThemeHeaderContentWidgets
列出、插入、替换和删除主题页眉中的小组件。
ThemeHeaders
添加、编辑、删除和检测主题页眉。
ThemePageContentWidgets
列出、插入、替换和删除主题页面中的小组件。
ThemePages
添加、编辑、删除和检测主题页面。
Themes
列出特定主题类型的主题。
Constants
以下 API 提供用于 UI 自动化服务的常量:
ContentWidgetWrappingFormats
用于与内容小组件相关服务的平台定义的小组件包装格式常量。
LayoutRegions
平台定义的布局区域常量,用于放置在内容小组件相关服务中的小组件。
ThemeableApplicationIds
用于标识站点应用程序标识符的常量。
ThemeProperties
用于与 ThemeFiles 服务交互的主题属性的常量。
ThemeTypes
要与其他 UI 自动化 API 一起使用的平台定义主题类型常量。
使用 UI 自动化 API
在以下几种常见情况下,你将使用 UI 自动化 API:
- 自定义应用程序或自定义功能定义新页面(请参阅页面定义和 URL 路由),并希望包含新页面的主题特定变体以简化安装。为此,请使用主题页眉、主题页面和主题页脚 API。
- 为一组自定义小组件实现的一组自定义功能(通过 IScriptedContentWidgetFactoryDefaultProvider),需要将源小组件文件作为自定义功能插件的一部分进行安装。为此,请参阅管理小组件源和分发。
- 有自定义小组件的自定义应用程序需要在现有页面上安装一个或多个自定义小组件。为此,请使用 ThemeHeaderContentWidgets、ThemePageContentWidgets 和 ThemeFooterContentWidgets API。
- CSS 文件要以编程方式安装在主题中,以便进行常规自定义(可能作为自动部署过程的一部分)或作为自定义应用程序的一部分。为此,请参阅下面的 ThemeFiles API 和“安装 CSS 文件”示例。
示例:安装 CSS 文件
在此示例中,将在网站主题中安装硬编码的 CSS 文件。当小组件共享公共 CSS 或 LESS 文件时,这是通过 IScriptedContentWidgetFactoryDefaultProvider 部署小组件的常见情况(请参见管理小组件源和分发)。
为了通过代码与平台集成并访问进程 API,该示例将在名为 InstallCssFile 的公共类中实现 IPlugin 接口。为了确保仅在需要安装时(首次启用插件或安装新版本时)安装 CSS 文件,InstallCssFile 类还实现了 IInstallablePlugin 接口。为了实现该类,项目需要引用 Limyee.Api.dll 和 Limyee.Components.dll。
完整的源代码位于本页的底部,但 UI 自动化 API 的主要用法发生在 Install 和 Uninstall 方法中:
public void Install(Version lastInstalledVersion) { foreach (var theme in Themes.List(ThemeTypes.Site)) { ThemeFiles.AddUpdateFactoryDefault( theme, ThemeProperties.StyleSheetFiles, _fileName, _fileStream, (int)_fileStream.Length, new CssThemeFileOptions { ApplyToModals = true, ApplyToNonModals = true } ); ThemeFiles.AddUpdate( theme, ThemeableApplicationIds.Site, ThemeProperties.StyleSheetFiles, _fileName, _fileStream, (int)_fileStream.Length, new CssThemeFileOptions { ApplyToModals = true, ApplyToNonModals = true } ); } }
在 Install 中,插件在每个可用的站点主题上循环(使用 ThemeTypes 和 Themes API)。对于每个主题,它将 CSS 文件的出厂默认版本和同一文件安装到网站主题的当前上下文版本中(使用 ThemeFiles、ThemeProperties 和 ThemeableApplicationIds API)。将 CSS 文件安装到 ThemeProperties.StyleSheetFiles 主题属性时,可以使用 CssThemeFileOptions 定义 CSS 选项。在此示例中,插件标识文件应在主题的模态和非模态页面上渲染。
public void Uninstall() { foreach (var theme in Themes.List(ThemeTypes.Site)) { ThemeFiles.RemoveFactoryDefault(theme, ThemeProperties.StyleSheetFiles, _fileName); ThemeFiles.Remove(theme, ThemeableApplicationIds.Site, ThemeProperties.StyleSheetFiles, _fileName); } }
卸载时,将调用 Uninstall 方法,插件再次循环访问可用主题,并从每个主题的出厂默认和上下文删除已安装的 CSS 文件。
此示例的完整来源如下:
using System; using System.Text; using Limyee.Extensibility.Version1; using Limyee.Extensibility.UI.Version1; namespace Samples { public class InstallCssFile : IPlugin, IInstallablePlugin { private readonly string _fileName = "sample.css"; private readonly System.IO.Stream _fileStream = new System.IO.MemoryStream(Encoding.UTF8.GetBytes(@".content-fragment-page { background-color: #f00; }")); #region IPlugin Implementation public string Name { get { return "Install a CSS File Sample"; } } public string Description { get { return "Installs a CSS File in the Site theme."; } } public void Initialize() { } #endregion #region IInstallablePlugin Implementation public Version Version { get { return new Version(1, 0); } } public void Install(Version lastInstalledVersion) { foreach (var theme in Themes.List(ThemeTypes.Site)) { ThemeFiles.AddUpdateFactoryDefault( theme, ThemeProperties.StyleSheetFiles, _fileName, _fileStream, (int)_fileStream.Length, new CssThemeFileOptions { ApplyToModals = true, ApplyToNonModals = true } ); ThemeFiles.AddUpdate( theme, ThemeableApplicationIds.Site, ThemeProperties.StyleSheetFiles, _fileName, _fileStream, (int)_fileStream.Length, new CssThemeFileOptions { ApplyToModals = true, ApplyToNonModals = true } ); } } public void Uninstall() { foreach (var theme in Themes.List(ThemeTypes.Site)) { ThemeFiles.RemoveFactoryDefault(theme, ThemeProperties.StyleSheetFiles, _fileName); ThemeFiles.Remove(theme, ThemeableApplicationIds.Site, ThemeProperties.StyleSheetFiles, _fileName); } } #endregion } }