许多插件类型都会渲染内容,通常是HTML内容。虽然此内容可以完全在代码中生成,但插件也可以选择向小组件公开部分或全部渲染功能,并可以选择允许管理员使用小组件编辑器自定义插件 UI。
任何支持渲染内容的插件都可以选择使用小组件公开其部分或全部输出。可以使用此选项来简化渲染的定义,或使管理员能够使用小组件编辑器对渲染的内容进行更改。
要添加插件支持定义通过小组件进行内容渲染,插件必须实现 IScriptablePlugin 接口。IScriptablePlugin 接口在 Limyee.ScriptedContentWidgets.dll 的 Limyee.Extensibility.UI.Version1 命名空间中定义。实现此接口时,还需要将插件作为出厂默认小组件提供程序,并且插件使用的小组件实现脚本应存储在出厂默认提供程序实现的文件夹结构中(有关小组件源文件管理的更多详细信息,请参阅出厂默认小组件提供程序主题):
using System;
using Limyee.Extensibility.UI.Version1;
namespace Samples
{
public class SampleScriptablePlugin : IScriptablePlugin
{
// This must be unique for each widget defined by this plugin
private readonly Guid _widgetId = new Guid("750364A8-CAA9-45D6-B14E-5D0F60BD70E2");
private IScriptedContentWidgetController _scriptController;
#region IPlugin
// ...
#endregion
#region IScriptedContentWidgetFactoryDefaultProvider
// ...
#endregion
#region IScriptablePlugin
public void Register(IScriptedContentWidgetController controller)
{
_scriptController = controller;
var widgetOptions = new ScriptedContentWidgetOptions(_widgetId)
{
CanBeThemeVersioned = false,
CanHaveHeader = false,
CanHaveWrapperCss = false,
CanReadPluginConfiguration = false,
CanWritePluginConfiguration = false,
IsEditable = false
};
_scriptController.Register(widgetOptions);
}
#endregion
// Get the name, description, cache configuration, CSS class using _scriptController.GetMetadata(_widgetId);
// Get the header of the widget using _scriptController.RenderHeader(_widgetId, null)
// Render the widget using _scriptController.Render(_widgetId, null)
}
}
单个插件可以定义多个小组件,以满足插件的特定渲染需求(一般实现另一个插件接口)。当调用 IScriptablePlugin 的 Register 方法时,插件应使用提供的控制器的 Register 方法注册每个小组件。控制器的 Register 方法使插件能够配置小组件的工作方式,详情如下:
使用小组件进行渲染的插件可以选择在注册小组件时,填充 Extensions 选项来向它定义特定的小组件私有 API。对上一示例版本修改,片段注册包括一个自定义扩展:
using System;
using Limyee.Extensibility.UI.Version1;
using System.Collections.Specialized;
namespace Samples
{
public class SampleScriptablePlugin : IScriptablePlugin
{
private readonly Guid _widgetId = new Guid("750364A8-CAA9-45D6-B14E-5D0F60BD70E2");
private IScriptedContentWidgetController _scriptController;
#region IPlugin
// ...
#endregion
#region IScriptedContentWidgetFactoryDefaultProvider
// ...
#endregion
#region IScriptablePlugin
public void Register(IScriptedContentWidgetController controller)
{
_scriptController = controller;
var widgetOptions = new ScriptedContentWidgetOptions(_widgetId)
{
CanBeThemeVersioned = false,
CanHaveHeader = false,
CanHaveWrapperCss = false,
CanReadPluginConfiguration = false,
CanWritePluginConfiguration = false,
IsEditable = false
};
widgetOptions.Extensions.Add(new SamplePrivateExtension());
_scriptController.Register(widgetOptions);
}
#endregion
// Get the name, description, cache configuration, CSS class using _scriptController.GetMetadata(_widgetId);
// Get the header of the widget using _scriptController.RenderHeader(_widgetId, null)
// Render the widget using _scriptController.Render(_widgetId, null)
}
public class SamplePrivateExtension : IContextualScriptedContentWidgetExtension
{
#region IContextualScriptedContentWidgetExtension
public string ExtensionName { get { return "private"; } }
public object GetExtension(NameValueCollection context)
{
return new SamplePrivateExtensionApi(context);
}
#endregion
}
public class SamplePrivateExtensionApi
{
private NameValueCollection _context;
public SamplePrivateExtensionApi(NameValueCollection context)
{
_context = context;
}
public string Value
{
get { return _context == null ? null : _context["Value"]; }
}
}
}
在此示例中,注册插件定义的小组件(ID 是 _widgetId)时,在第 41 行同时也注册了一个私有 API:SamplePrivateExtension 类。SamplePrivateExtension 类使用 SamplePrivateExtensionApi 类定义其 API, API 名称是 private,该名称可供给其小组件使用 “$private” 的方式访问。SamplePrivateExtensionApi 上的任何公共属性和方法都向小组件公开,以便在实现此渲染的输出时使用。
请注意,私有扩展提供了上下文的 NameValueCollection。在渲染插件定义的小组件的内容脚本或标头时,插件可以提供一组上下文数据 NameValueCollection。此上下文数据传递到私有扩展,私有扩展可以使用上下文来更改其功能。
在上面的示例中,扩展希望接收名为 “Value” 的上下文值。定义小组件的插件将负责在渲染小组件时提供此值(有关示例,请参阅下一节)。
现在,您已经拥有了由插件定义的一个或多个小组件,现在您可以使用这些插件来实现其他插件类型,并提供渲染输出。无论返回字符串或可以写入 TextWriter 的任何地方,插件都可以渲染其小组件。例如,使用前面的示例,插件可能有一个属性 Content,该属性是小组件应渲染的字符串。它可以传递上下文值并由定义为 _widgetId 的小组件来渲染,实现此属性后可供其他插件使用:
public string Content
{
get
{
return _scriptController.RenderContent(_widgetId, new NameValueCollection() { { "Value", "Test" } });
}
}
在 _widgetId 定义的小组件中,调用 "$private.Value" 将返回 "Test"。小组件本身可以执行小组件支持的任何操作,包括创建 Ajax 回调,使用嵌入式文件等。
由插件定义的小组件可以执行常规小组件可以执行的所有操作,除了定义它们的插件启用的功能之外,还可以访问任何提供的私有 API。
实现插件定义的小组件时,最大的考虑因素是,您不可能只依赖于现有小组件 API 的上下文值。例如,除非小组件作为扩展执行 UI 请求,否则 $limyee_v1_blogPost.Current 可能永远不会有值,$limyee_v1_page.GetFormValue() 通常也没有值,因为他们依赖的是当前的 UI 请求,而不是 API 的上下文值。