Composite C1 架构如何工作?

发布于 2024-12-12 19:05:28 字数 158 浏览 4 评论 0原文

谁能对 Composite C1 核心中发生的情况进行高级描述?我特别有兴趣了解插件架构如何工作以及系统的核心组件是什么,即当请求到达时架构中发生了什么。描述不必太详细,只需列出步骤和所涉及的类即可。

希望核心开发团队之一能够启发我...并且也许会发布更多 API(请提示更多类文档)。

Can anyone give a high level description of what is going on in the Composite C1 core? In particular I am interested in knowing how the plugin architecture works and what the core components are of the system i.e. when a request arrives what is happening in the architecture. The description doesn't have to be too verbose just a list of steps and the classes involved.

Hopefully one of the core development team would enlighten me... and maybe publish some more API (hint hint more class documentation please).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

司马昭之心 2024-12-19 19:05:29

从请求到呈现的页面

请求所采用的具体路径取决于您所使用的 C1 版本,因为在 2.1.2 版本中它已更改为使用路由。那么让我们看看

  • < 2.1.2

Composite.Core.WebClient.Renderings.RequestInterceptorHttpModule 将拦截所有传入请求并确定请求的路径是否对应于有效的 C1 页面。如果是,URL 将被重写到 C1 页面处理程序 ~/Rendererings/Page.aspx

  • 2.1.1

Composite.Core.Routing.Routing.Routes.Register() 将 C1 页面路由 (Composite.Core.Routing.Pages.C1PageRoute) 添加到 Routes-collection查看传入路径,确定其是否为有效的 C1 页面。如果是,它返回一个准备执行的 ~/Rendererings/Page.aspx 实例。

好的,现在我们有一个 IHttpHandler 实例,准备好组成要返回给客户端的页面。 IHttpHandler 的实际代码很容易看到,因为它位于 ~/Renderers/Page.aspx.cs 中。

  • OnPreInit

在这里,我们计算出所请求的页面 ID 和语言,并查看我们是否处于预览模式、哪个数据范围等。

  • OnInit

现在,我们从页面的每个内容占位符中获取内容,并且执行它可能包含的功能。它是通过调用 Composite.Core.WebClient.Renderings.Page.PageRenderer.Render 并传递当前页面和占位符来完成的。在内部,它将调用方法 ExecuteFunctions,该方法将遍历内容并递归解析 C1 函数元素 (),执行它们并替换元素与函数输出。这将一直完成,直到内容中不再有函数元素,以防函数本身输出其他函数。

现在,整个内容都包装在 Asp.Net WebForms 控件中,并插入到我们的 WebForms 页面中。由于 C1 函数可以返回诸如 UserControl 等 WebForms 控件,因此这对于它们正常工作并触发 WebForms 的事件生命周期是必要的。

而且,基本上就是这样。所请求页面的呈现非常简单并且非常可扩展。例如,是否有一个扩展可以使用 MasterPages,它可以非常优雅地挂钩到此渲染流程。因为我们使用 Routing 来映射要使用的处理程序,所以也可以忘记 ~/Rendering/Page.aspx 并只返回 MvcHandler< /code> 如果您是 Mvc 狂热者。

API

现在,说到更核心的 API,有很多,具体取决于您想要做什么。但您可以非常确定,无论发生什么,都有必要的条件来完成工作。

在最深处,我们有数据层,大多数其他 API 和外观都以数据层为中心。这意味着您可以使用原始数据完成大多数事情,而不是一直通过外观。这是可能的,因为 C1 的大多数配置都是通过使用其自己的数据层来存储配置来完成的。

Composite C1 核心小组尚未验证/重构和记录系统中的所有 API,因此以“公共 API”的概念以及在有需求时可以成为 API 的概念进行操作。后者是一个相当稳定的 API,但没有保证。

公共 API 文档在线位于 http://api.composite.net/

函数

是 C1 的基本组成部分,是一种从执行中抽象逻辑的技术。基本上,执行操作或返回某些数据/字符串/值的所有内容都可以成为函数的候选者。在最低级别,函数是实现 IFunction 接口的 .Net 类,但幸运的是,有许多更简单的方法可以使用它。 开箱即用 C1 支持定义为 XSLT 的函数模板、C# 方法或 Sql。还有社区支持使用 Razor 编写函数或将 ASP.Net UserControls(.ascx 文件)作为函数。

由于所有函数在系统启动期间都在 C1 中注册,因此我们使用 Composite.Functions.FunctionFacade 来执行我们知道名称的任何函数。使用 GetFunction 获取对函数的引用,然后使用 Execute 执行该函数并获取返回值。函数可以采用在执行函数时作为真实 .Net 对象传递的参数。还完全支持使用 元素通过 Xml 标记调用函数,这意味着编辑者、设计者、模板制作者等可以轻松访问丰富的功能,而无需知道如何编写.Net 代码。

在此处了解有关函数的更多信息 http://users.composite.net/C1/Functions.aspx 以及如何使用 ie Razor 在此处创建函数 http://docs.composite.net/C1/ASP-NET/Razor-Functions.aspx

全球化和本地化

C1 具有完整的多语言支持核心。 Composite.Core.Localization.LocalizationFacade 用于管理系统中已安装的语言环境;查询、添加和删除。区域设置可以是系统已知的任何 CultureInfo 对象。

Composite.Core.ResourceSystem.StringResourceSystemFacade 用于在运行时获取与您的请求运行所在的 CultureInfo 相匹配的字符串。使用此方法,而不是在页面或模板中硬编码字符串。

在此处阅读有关本地化的更多信息 http://docs.composite.net/C1/HTML /C1-Localization.aspx

全局事件

Composite.C1Console.Events.GlobalEventSystemFacade 对于了解您是否需要跟踪何时发生事件非常重要系统正在关闭,因此您可以进行最后一刻的更改。由于 C1 是高度多线程的,因此很容易为 C1 编写多线程的扩展和模块,利用多核系统和并行化,因此以正确的方式关闭线程也至关重要。 GlobalEventSystemFacade 可以帮助您做到这一点。

启动活动
如果您编写插件,这些插件可以有一个自定义工厂。其他代码可以使用 ApplicationStartupAttribute 属性来调用Web 应用程序启动时的 Composite C1 核心。

数据事件
您可以使用 < 上的静态方法订阅数据添加、编辑和删除事件(前置和后置)代码>Composite.Data.DataEvents。要在系统启动时附加到这些事件,请使用 ApplicationStartupAttribute< /a> 属性。

数据

如果您在相应的 C1 页面请求之外访问数据层, Composite.Core.Threading.ThreadDataManager 非常重要。这可能是一个自定义处理程序,只需将所有最新新闻作为 Rss 提要提供,或者您可能编写一个控制台应用程序。在这些情况下,请始终记住包装访问数据的代码,如下所示

using(Composite.Core.Threading.ThreadDataManager.EnsureInitialize())
{
  // Code that works with C1 data layer goes here
}

对于访问和操作数据,建议不要使用 DataFacade 类,而是包装所有获取、更新、删除或添加数据的代码,如

using(var data = new DataConnection())
{
   // Do things with data
}

IO< /strong>

在处理文件和目录时,重要的是使用 .Net 文件的 C1 等效类 Composite.Core.IO.C1FileComposite.Core.IO.C1Directory和目录。这是因为 C1 可以托管在 Azure 上,而您可能不可以可以像访问普通 Windows Server 一样访问文件系统。通过使用 C1 的文件和目录包装器,您可以确保您编写的代码也能够在 Azure 上运行。

C1 控制台

控制台本身就是一个完整的主题,并且有很多 API。

您可以使用 Composite.C1Console.Trees.TreeFacade 或 Composite.C1Console.Elements.ElementFacade 并实现 Composite.C1Console.Elements.Plugins 创建自己的树。 ElementProvider.IElementProvider。

您可以使用Composite.C1Console.Events.ConsoleMessageQueueFacade将消息从服​​务器发送到客户端,使其执行诸如打开消息框、刷新树、将焦点设置在特定元素上、打开 Composite.C1Console.Workflow.WorkflowFacade

用于获取特定工作流程的实例并与它们交互。 工作流是C1的一个非常基本的部分,是定义和执行多步骤操作的方式。这使得可以保存操作状态,即。即使服务器重新启动或发生任何其他意外情况,10 步向导也会持续存在。 工作流是使用Windows Workflow Foundation构建的,因此您对此熟悉吗?您应该感到宾至如归

。在向控制台编写扩展时,您还可以使用大量的 javascript 外观和方法。比我在这里所能涵盖的内容要多得多,所以我什至不会在这里开始讨论这个主题。

composite.config

C1 的一个基本部分是提供程序,几乎所有内容都由提供程序组成,甚至包括许多核心功能。控制台中从视角到树以及元素和操作的所有内容都通过提供程序输入到 C1 中。所有标准函数、数据层和所有与函数调用编辑器一起使用的小部件都通过提供程序馈送到 C1 中。与资源、用户和权限、url 格式化程序等一起使用的所有本地化字符串都是提供者。

  • Composite.Data.Plugins.DataProviderConfiguration

此处注册了所有可以响应 DataFacade 上的方法、Get、Update、Delete、Add 等的提供程序。每个提供者都会通知系统它可以与哪些接口交互,C1 确保将特定接口的所有请求路由到各自的数据提供者。

  • Composite.C1Console.Elements.Plugins.ElementProviderConfiguration

在这里,我们定义控制台内的透视图和树。您第一次启动控制台时看到的所有标准视角都在此处配置,不涉及任何魔法或黑匣子。

  • Composite.C1Console.Elements.Plugins.ElementActionProviderConfiguration

操作提供者能够根据其 EntityToken 向系统中的所有元素添加新的菜单项。当您想要向现有内容添加新功能(例如版本控制、外联网安全、自定义剪切/粘贴等)时,此功能非常强大。

  • Composite.C1Console.Security.Plugins.LoginProviderConfiguration

LoginProvider 是 C1 控制台用来验证用户身份并允许您登录或不登录的内容。不幸的是,这不是很开放,但经过一些思考,你应该已经准备好了。

  • Composite.Functions.Plugins.FunctionProviderConfiguration

Composite C1 将使用所有注册的 FunctionProvider 在系统启动时填充其内部函数列表。

  • Composite.Functions.Plugins.WidgetFunctionProviderConfiguration

WidgetProviders 用于函数调用编辑器或表单标记等中,以呈现用于选择数据的自定义 UI。

  • Composite.Functions.Plugins.XslExtensionsProviderConfiguration

在 XSLT 模板中使用的自定义扩展在此处注册。

然后我们有一些用于纯配置的部分,例如缓存或要并行化的内容,但它不如提供程序那么有趣。

定义和使用节

composite.config 和其他相关 .config 文件中的节是完全标准的 .Net 配置并遵守其规则。这意味着能够使用自定义元素,例如 ie。 Composite.Functions.Plugins.WidgetFunctionProviderConfiguration 它必须被定义为一个部分。节有一个名称并引用从 System.Configuration.ConfigurationSection 继承的类型。 Composite 使用 Microsoft 企业库来处理大多数常见事务,例如配置、日志记录和验证,因此所有 Composite 部分都继承自 Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SerializesConfigurationSection。现在,这种类型只需具有我们希望能够在 .config 文件中定义的所有元素的属性,并且 .Net 将自动确保为我们连接起来。

如果您想访问特定部分的配置,您可以调用Composite.Core.Configuration.ConfigurationServices.ConfigurationSource.GetSection("..section name")并将其转换为您的特定类型和您的好去。

向已定义的部分添加额外的属性

通常,如果您在 .config 文件中编写的元素或属性无法被负责该部分或元素的类型识别,则 .Net 会发出警告。这使得编写一个真正灵活的模块系统变得困难,外部作者可以在其中向其提供者添加特定的配置选项,因此我们有了汇编器的概念。它是一个 ConfigurationElement 类,分配了一个 Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.AssemblerAttribute 属性,而该属性又采用一个 Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder。 IAssembler 接口作为参数,负责从 .config 文件中的元素获取这些自定义属性和值,并从中发出可用的对象。 读取配置时获取它们

这样,.Net 就不会抱怨无效的 .config 文件,因为我们注入了一个 ConfigurationElement 对象,该对象具有所有自定义属性的属性,并且我们可以在通过 IAssembler Slides 。一些概述

幻灯片可以在这些链接上找到

灵感和示例

C1Contrib 项目很好地介绍了如何与 C1 的不同部分进行交互。它是一个小包的集合,可以直接使用,也可以作为灵感。有些包可以使用动态类型进行操作以启用接口继承。其他包在控制台中使用 javascript api,而其他包则展示如何为现有元素创建函数提供程序、树和挂钩命令。甚至还有如何操作客户端和服务器之间进行的 Soap Web 服务通信的示例,以便您可以让它按照您想要的方式执行操作。这样的例子还在继续。

From request to rendered page

The concrete path a request takes depends on the version of C1 you're using, since it was changed to use Routing in version 2.1.2. So lets see

  • < 2.1.2

Composite.Core.WebClient.Renderings.RequestInterceptorHttpModule will intercept all incoming requests and figure out if the requested path correspond to a valid C1 page. If it does, the url will be rewritten to the C1 page handler ~/Rendererings/Page.aspx

  • 2.1.1

Composite.Core.Routing.Routes.Register() adds a C1 page route (Composite.Core.Routing.Pages.C1PageRoute) to the Routes-collection that looks at the incoming path, figures out if its a valid C1 page. If it is, it returns an instance of ~/Rendererings/Page.aspx ready to be executed.

Okay, so now we have an instance of a IHttpHandler ready to make up the page to be returned to the client. The actual code for the IHttpHandler is easy to see since its located in ~/Renderers/Page.aspx.cs.

  • OnPreInit

Here we're figuring out which Page Id and which language that was requested and looking at whether we're in preview mode or not, which datascope etc.

  • OnInit

Now we're fetching the content from each Content Placeholder of our page, and excuting its functions it may contain. Its done by calling Composite.Core.WebClient.Renderings.Page.PageRenderer.Render passing the current page and our placeholders. Internally it will call the method ExecuteFunctions which will run through the content and recursively resolve C1 function elements (<f:function />), execute them and replace the element with the functions output. This will be done until there are no more function elements in the content in case functions them selves output other functions.

Now the whole content is wrapped in a Asp.Net WebForms control, and inserted into our WebForms page. Since C1 functions can return WebForms controls like UserControl etc., this is necessary for them to work correctly and trigger the Event Lifecycle of WebForms.

And, that's basically it. Rendering of a requested page is very simple and very extendable. For instance is there an extension that enables the usage of MasterPages which simply hooks into this rendering flow very elegantly. And because we're using Routing to map which handler to use, its also possible to forget about ~/Rendering/Page.aspx and just return a MvcHandler if your a Mvc fanatic.

API

Now, when it comes to the more core API's there are many, depending on what you want to do. But you can be pretty sure, no matter what there is the necessary ones to get the job done.

At the deep end we have the Data Layer which most other API's and facades are centered around. This means you can do most things working with the raw data, instead of going through facades all the time. This is possible since most configuration of C1 is done by using its own data layer to store configuration.

The Composite C1 core group have yet to validate/refactor and document all the API's in the system and hence operate with the concept of 'a public API' and what can become an API when the demand is there. The latter is a pretty darn stable API, but without guarantees.

The public API documentation is online at http://api.composite.net/

Functions

Functions is a fundamental part of C1 and is a technique to abstract logic from execution. Basically everything that either performs a action or returns some data/string/values can be candidates for functions. At the lowest level a function is a .Net class implementing the IFunction interface, but luckily there are many easier ways to work with it. Out of the box C1 supports functions defined as XSLT templates, C# methods or Sql. There are also community support for writing functions using Razor or having ASP.Net UserControls (.ascx files) to be functions.

Since all functions are registered in C1 during system startup, we use the Composite.Functions.FunctionFacade to execute whatever function we know the name of. Use the GetFunction to get a reference to a function, and then Execute to execute it and get a return value. Functions can take parameters which are passed as real .Net objects when executing a function. There is also full support for calling functions with Xml markup using the <f:function /> element, meaning that editors, designers, template makers etc. easily can access a wealth of functionality without having to know how to write .Net code.

Read more about functions here http://users.composite.net/C1/Functions.aspx and how to use ie Razor to make functions here http://docs.composite.net/C1/ASP-NET/Razor-Functions.aspx

Globalization and Localization

C1 has full multi-language support in the core. Composite.Core.Localization.LocalizationFacade is used for managing the installed locales in the system; querying, adding and removing. Locales can be whatever CultureInfo object is known by your system.

Composite.Core.ResourceSystem.StringResourceSystemFacade is used for getting strings at runtime that matches the CultureInfo your request is running in. Use this, instead of hardcoding strings on your pages or in your templates.

Read more about Localization here http://docs.composite.net/C1/HTML/C1-Localization.aspx

Global events

Composite.C1Console.Events.GlobalEventSystemFacade is important to know if you need to keep track on when the system is shutting down so you can make last-minute changes. Since C1 is highly multithreaded its easy to write extensions and modules for C1 that are multithreaded as well, taking advantage of multi core systems and parallelization and therefor its also crucial to shut down ones threads in a proper manner. The GlobalEventSystemFacade helps you do that.

Startup events
If you write plug-ins these can have a custom factory. Other code can use the ApplicationStartupAttribute attribute to get called by the Composite C1 core when the web app start up.

Data events
You can subscribe to data add, edit and delete events (pre and post) using the static methods on Composite.Data.DataEvents<T>. To attach to these events when the system start up, use the ApplicationStartupAttribute attribute.

Data

Composite.Core.Threading.ThreadDataManager is important if your accessing the Data Layer outside of a corresponding C1 Page request. This could be a custom handler that just has to feed all newest news as a Rss feed, or your maybe writing a console application. In these cases, always remember to wrap your code that accesses the data like this

using(Composite.Core.Threading.ThreadDataManager.EnsureInitialize())
{
  // Code that works with C1 data layer goes here
}

For accessing and manipulating data its recommended NOT to use the DataFacade class, but wrap all code that gets or updates or deletes or adds data like this

using(var data = new DataConnection())
{
   // Do things with data
}

IO

When working with files and directories its important to use the C1 equivalent classes Composite.Core.IO.C1File and Composite.Core.IO.C1Directory to .Net's File and Directory. This is due to the nature where C1 can be hosted on Azure, where you might not have access to the filesystem in the same way as you have on a normal Windows Server. By using the C1's File and Directory wrappers you can be sure that code you write will be able to run on Azure as well.

C1 Console

The console is a whole subject on itself and has many many API's.

You can create your own trees using Composite.C1Console.Trees.TreeFacade or Composite.C1Console.Elements.ElementFacade and implementing a Composite.C1Console.Elements.Plugins.ElementProvider.IElementProvider.

You can use the Composite.C1Console.Events.ConsoleMessageQueueFacade to send messages from the server to the client to make it do things like open a message box, refreshing a tree, set focus on a specific element, open a new tab etc. etc.

Composite.C1Console.Workflow.WorkflowFacade is used for getting instances of specific workflows and interacting with them. Workflows is a very fundamental part of C1 and is the way multi-step operations are defined and executed. This makes it possible to save state of operation so ie. a 10 step wizard is persisted even if the server restarts or anything else unexpected happens. Workflows are build using Windows Workflow Foundation, so are you familiar with this, you should be feeling at home

There is also a wealth of javascript facades and methods you can hook into when writing extensions to the Console. Much more than i could ever cover here so i will refrain myself from even getting started on that subject here.

composite.config

A fundamental part of C1 is providers, almost everything is made up of providers, even much of the core functionality. Everything in the console from Perspectives to Trees and elements and actions are feeded into C1 with providers. All the standard functions, the datalayer and all the widgets for use with the Function Call editor is feeded into C1 with providers. All the localisation strings for use with the Resources, users and permissions, url formatters etc. is all providers.

  • Composite.Data.Plugins.DataProviderConfiguration

Here all providers that can respond to the methods on DataFacade, Get, Update, Delete, Add etc. are registered. Every provider informs the system which interfaces it can interact with and C1 makes sure to route all requests for specific interfaces to their respective dataproviders.

  • Composite.C1Console.Elements.Plugins.ElementProviderConfiguration

Here we're defining the perspectives and the trees inside the Console. All the standard perspectives you see when you start the Console the first time are configured here, no magic or black box involved.

  • Composite.C1Console.Elements.Plugins.ElementActionProviderConfiguration

Action providers are able to add new menuitems to all elements in the system, based on their EntityToken. This is very powerful when you want to add new functionality to existing content like versioning, extranet security, custom cut/paste and the list goes on.

  • Composite.C1Console.Security.Plugins.LoginProviderConfiguration

A LoginProvider is what the C1 console will use to authenticate a user and let you log in or not. Unfortunately this isn't very open but with some reflection you should be all set.

  • Composite.Functions.Plugins.FunctionProviderConfiguration

Composite C1 will use all the registered FunctionProviders to populate its internal list of functions on system startup.

  • Composite.Functions.Plugins.WidgetFunctionProviderConfiguration

WidgetProviders are used in things like the Function Call Editor or in Forms Markup to render custom UI for selecting data.

  • Composite.Functions.Plugins.XslExtensionsProviderConfiguration

Custom extensions for use in XSLT templates are registered here

And then we have a few sections for pure configuration, like caching or what to to parallelize but its not as interesting as the providers.

Defining and using sections

Sections in composite.config, and other related .config files are completely standard .Net configuration and obeys the rules thereof. That means that to be able to use a custom element, like ie. Composite.Functions.Plugins.WidgetFunctionProviderConfiguration it has to be defined as a section. A section has a name and refers to a type that would inherit from System.Configuration.ConfigurationSection. Composite uses the Microsoft Enterprise Libraries for handling most of these common things like configuration and logging and validation and therefor all Composites sections inherit from Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SerializableConfigurationSection. Now, this type just has to have properties for all the elements we want to be able to define in the .config-file, and .Net will automatically make sure to wire things up for us.

If you want to access configuration for a particular section you would call Composite.Core.Configuration.ConfigurationServices.ConfigurationSource.GetSection(".. section name") and cast it to your specific type and your good to go.

Adding extra properties to already defined sections

Normally .Net would complain if you write elements or attributes in the .config files that aren't recognized by the type responsible for the section or for the element. This makes it hard to write a truly flexible module-system where external authors can add specific configuration options to their providers, and therefor we have the notion of a Assembler. Its a ConfigurationElement class with a Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.AssemblerAttribute attribute assigned to it that in turns takes a Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder.IAssembler interface as argument that is responsible for getting these custom attributes and values from the element in the .config file and emit usable object from it. This way .Net won't complain about an invalid .config file, since we inject a ConfigurationElement object that has properties for all our custom attributes, and we can get hold of them when reading the configuration through the IAssembler

Slides

Some overview slides can be found on these lins

Inspiration and examples

The C1Contrib project on GitHub is a very good introduction how to interact with the different parts of C1. Its a collection of small packages, that can be used as it is, or for inspiration. There are packages that manipulates with dynamic types to enable interface inheritance. Other packages uses the javascript api in the console, while others show how to make Function Providers, Trees and hook commands unto existing elements. There is even examples of how to manipulate with the Soap webservice communication going on between client and server so you can make it do things the way you want it. And the list goes on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文