Orchard(三):搞清来龙去脉(3)-Orchard 是怎么运行的?

33 篇文章 0 订阅

之前系列文章

Orchard(一):介绍

Orchard (二):简单配置

Orchard(三):搞清来龙去脉(1)-初探

Orchard(三):搞清来龙去脉(2)-Widgets

之前使用总结

    这几天,我专门去用了一下Orchard。有一些比较浅的体验:总的说来,Orchard使用起来可配置性好。

    举个例子:想在网站上加入一个搜索引擎,只需要下一个提供程序,配置一下就可以。

其中有两个亮点:

一、Orchard可以部署到微软云服务上(Windows Azure);

二、在跑网站时,可以用一个应用程序域跑多个站点(专业名词叫做 multi-tenant )--这样可以降低服务器性能,多一个域就多了内存管理,....。

网站大致架构

                                                                                   【图一】

实际项目

 

 

            

基础架构说明

 由【图一】,我们可以看清,下面几种开源组件

  • ASP.NET MVC:这是微软开源的基于MVC的Web开发框架
  • NHibernate:NHibernate 是一个ORM工具,从Hibernate演化而来
  • Autofac: 一个IoC container。Orchard大量使用依赖注入
  • Castle Dynamic Proxy: Castle 是.Net中很早就出现的一个开源项目,Castle Dynamic Proxy是一个生产动态代理。

    一、Orchard Framework

         Orchard框架最深的一层。它包含的应用程序或至少部分不能隔离到模块的引擎,甚至连最基本的模块都要依赖于它,可以把它看作是对Orchard的基类库

     

    (一)Orchard启动

     1.当Orchard web应用启动后,生成一个应用域级别的单例的Orchard Host(DefaultOrchardHost)

      代码:

      

     protected void Application_Start() {
                RegisterRoutes(RouteTable.Routes);
                _starter = new Starter<IOrchardHost>(HostInitialization, HostBeginRequest, HostEndRequest);
                _starter.OnApplicationStart(this);
            }

    相关代码:

            private static IOrchardHost HostInitialization(HttpApplication application) {
                var host = OrchardStarter.CreateHost(MvcSingletons);
    
                host.Initialize();
    
                // initialize shells to speed up the first dynamic query
                host.BeginRequest();
                host.EndRequest();
    
                return host;
            }
    
            static void MvcSingletons(ContainerBuilder builder) {
                builder.Register(ctx => RouteTable.Routes).SingleInstance();
                builder.Register(ctx => ModelBinders.Binders).SingleInstance();
                builder.Register(ctx => ViewEngines.Engines).SingleInstance();
            }

        2. 获取通过ShellContextFactory获取当前tenant的Shell

      (tenant:占用者,占用户;主要是可以让多个网站在同一个域里面执行,减少服务器的损耗)

      ""

            private static IOrchardHost HostInitialization(HttpApplication application) {
                var host = OrchardStarter.CreateHost(MvcSingletons);

                host.Initialize();

                // initialize shells to speed up the first dynamic query
                host.BeginRequest();
                host.EndRequest();

                return host;
            }

            static void MvcSingletons(ContainerBuilder builder) {
                builder.Register(ctx => RouteTable.Routes).SingleInstance();
                builder.Register(ctx => ModelBinders.Binders).SingleInstance();
                builder.Register(ctx => ViewEngines.Engines).SingleInstance();
            }

    HostInitializationHostInitialization

    这个Shell相当于Tenant的实例,它会做以下事情,我简单翻译一下,附带原文。

  • 1. 首先,这个Shell会从ExtensionManager中获取modules 和 themes,默认操作是去扫描modules 和 themes对应的目录。( will get the list of available extensions from the ExtensionManager. Extensions are modules and themes. The default implementation is scanning the modules and themes directories for extensions.)

  • 2. 在进行第1步的同时,shell会从ShellSettingsManager获取tenant 的配置文件(默认是AppData中,当然也可以设置到其他地方)。(the shell will get the list of settings for the tenant from the ShellSettingsManager. The default implementation gets the settings from the appropriate subfolder of Appdata but alternative implementations can get those from different places. )

  • 3.  接下来,shell获取CompositionStrategy 实例。CompositionStrategy 实例将为当前tenant的Ioc Container容器准备需要扩展组件,依赖项;返回结果是ShellBlueprint,它是一系列依赖组件,控制器和record blueprints.( The shell then gets the CompositionStrategy object and uses it to prepare the IoC container from the list of available extensions for the current host and from the settings for the current tenant. The result of this is not an IoC container for the shell, it is a ShellBlueprint, which is a list of dependency, controller and record blueprints.)

    4.最后,这些ShellSetting(3所产生的,其实是tenant)和ShellBluePrint会被扔进ShellContainerFactory;CreateContainer将获取一个使IoC container 与 tenant关联的 ILifetimeScope的实例,这个ILifetimeScope实例使IoC container与 tenant关联,最终能使被注入的依赖项能与当前的Ioc Container关联。( The list of ShellSettings (that are per tenant) and the ShellBluePrint are then thrown into ShellContainerFactory.CreateContainer to get an ILifetimeScope, which is basically enabling the IoC container to be scoped at the tenant level so that modules can get injected dependencies that are scoped for the current tenant without having to do anything specific)

     (二) Dependency Injection(Orchard中的依赖注射)

       这里简单的说,在Orchard的创建注入项的标准方式是实现IDependency 接口,然后将该接口类型作为参数带入你的注入项的构造器中。然后,您就可以不做什么事了,Orchard会自己去发现这个注入项,并注入到对应的Tenant中。系统里默认的接口实例需要了解一下:

     

    Orchard默认接口实例

    Request

    IDependency

    处理新的Http请求

    Object

    ITransientDependency

    非共享实例,类似于用户的Session一人一份。

    Shell

    ISingletonDependency

    Tenant级别的,一个Tenant只能创建一个ISingletonDependency实例;用户保存objects的通用状态。

     

    一次执行中可能存在多个注入项,我们可以设置优先级,通过修改manifest

    Features:
        Orchard.Widgets.PageLayerHinting:
            Name: Page Layer Hinting
            Description: ...
            Dependencies: Orchard.Widgets
            Category: Widget
            Priority: -1
    

    注意:1.系统中已经存在的注入项是可以被替代的,通过在所实现的注入项上声明OrchardSuppressDependency 特性,即可。

               2.本文所说的依赖项和注入项,含义大致相同,指IoC Container的注入项。

    二、ASP.NET MVC

       Orchard使用微软MVC架构,这一点我们在用的时候再去理会。

    三、Content Type System

         在Ochard中(基于CMS的系统),为了提供弹性的,可重复使用的组件,它提供很多内容组件。

  •   简单说一下,在Orchard中Types(内容类型), Parts(内容组成部分), and Fields(字段、域)之前的关系:

    Types 是比较完整组件,比较一个Blog博客,它不已经是一个完整的功能。

    Parts  是Types 的组成部分;

    Fields 就类似于属性,是最小粒度的对象描述单位。   

    解析Content Type(后面补充,这一块儿,现在体会不深)

       Content Type由Content Part组成,Content Part对应一个Record,Record最终对应到存储。Content Type的实例在生命周期中,有事务处理

    四、Content Manager(内容管理者)

       在Orchard所有的内容,都是通过ContentManager 对象访问的(尽管试先,它是不知道内容类型的)。ContentManger 实例会查询内容(从存储过程中)、升级内容、内容的发布状态。

    五、 事务

       Orchard中的,所有的Http请求都被扔进了事务当中。也就是,一个操作如果中断,就会回滚到操作前的状态。

    注意:即使事务没有显示提交,但所有操作执行成功,Orchard会帮你提交此事务;这与.NET的事务机制不同(要想事务成功,需要提交;在using等实现Idispose接口里面,不显示回滚事务,.NET会自动帮你回滚)

    六、请求周期

       画个图吧,大致如此

       

    七、Widget

  •      和Content Type一样,具体同样组成部分、执行周期,其实任何Content Type都有可能成功Wedget。那么Wedget干什么的?

       Widget 是通过   Widget Layer最终被使用到页面上进行展示的。

             1. 通过Widget Layer(这里是Header Layer),将“Widget测试” 配置到首面(首页用了Header Layer)

             

     

             2. 显示

      八、事件总线(Event Bus)

    通常,Orchard 暴露扩展点,是通过实现接口来实现的,前的有具体的讲。但也可以有其他方式:

        1. 它可以不强制实现接口,也就是说,不会依赖接口程序集。

                   2.保证方法名字与所需要实现接口方法的名字相同,签名相同,就可以了。

    具体怎么做到的,我们以后再细看。

    事件总线大致的运行方式:当扩展点调用依赖实现时(被事先注入的实现),就会发布信息到事件总线上,由对象就会调用信息,进而调用对应的实现方法。

     

    九、Commands

      就是Windows 的cmd命令,在Orchard中,一些行为除了可以用管理界面,也可以使用命令行。

      Commands是通过ICommandHandler 暴露出来的。使用时直接在对应的方法上加特性就可以了。

      Commands 主要用途,可以用来模拟网站的实际运行状态。具体妙用,大家可以自行挖掘。

    十、Modules

      简而言之,一个Module是ASP.NET MVC area,附带一个manifest.txt (1.4中是 Module.txt文件)文件。

      既然是ASP.NET MVC area,基于Orchard机制,不难想像一个Module主要的组成部分为:事务处理程序,Content Type,Render Templete(告诉Orchard如果画页面)。

    十一、Theme(主题)

           Theme是Orhard的一个做得比较出众的地方,个人认为。其核心的思想是:所有产生的Html形式的数据,都可以被Mudule所产生的Theme、Html标签所替代

    机制:

    1. Orchard的整个Render机制是以Shape为基础的。Theme引擎的工作就是寻找到Theme,并且计算出Theme最合适的Shape方式。顺便提一下这个Shape,是一个Module组件,负责具体的展现工作的。
    2. Themes 具体继承机制。子类Theme可以实例化父类,使用父类主题。
    3. 网站选或者Tenant选择Theme是通过IThemeSelector实例对象做到的。Orchard目前的四个实现:SiteThemeSelector ,AdminThemeSelector ,PreviewThemeSelector ,SafeModeThemeSelector 。

    十二、其他

      Orchard还有运用的组件有:搜索引擎(Search and Indexing),缓存,文件系统(包含了Windows Azure的实现),用户角色、Module访问权限管理、任务(可制定计划调度Module)、通知机制(Module可以发送信息到管理界面)、Localization、日志(Castle.Core.Logging )。

      这些东西,不细写不因为不重要,是大家应该对这些熟知或有一定了解。本文的目的在于向你展示Orchard的整个脉络,不居泥于细节。

     

    总结:

      写这一篇真花了很长时间,最近事多,但总算完了。肯定有不足之外,后期完善,欢迎指正!

  • 下一篇 Orchard(四):创建Module --Hello World

     

     

     

          

     

     

     

      

     

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值