日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[翻译]Orchard如何工作

發布時間:2024/1/8 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [翻译]Orchard如何工作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Orchard一直是博主心中神一般的存在,由于水平比較菜,Orchard代碼又比較復雜看了幾次都不了了之了。這次下定決心要搞懂其工作原理,爭取可以在自己的項目中有所應用。為了入門先到官網去學習一下相關的基礎內容。看到這篇比較不錯的入門文章,邊學習邊翻譯一下。希望給有需要的朋友以幫助,也希望和對Orchard感興趣的朋友一起交流。

?

Orchard如何工作

構建一個Web內容管理系統不同于構建一個常規web應用:前者更像構建一個應用容器。設計一個這樣的系統,可擴展性應該放在第一位。這可能是一個挑戰因為增加可擴展性所必需的開放式架構可能會影響應用程序的可用性:系統的所有內容都需要與包括用戶界面在內的未知的模塊相組合使用。(感謝王老師提供的翻譯,對于原文那種巨長的讀起來就像沒加標點的文言文一樣的句子只能找外援了。)把這些彼此不了解的小模塊精心安排在一起組成一個連貫的整體正是Orchard所做的全部。

這個文檔解釋了Orchard架構選擇并說明了這些選擇的方案怎樣解決同時獲得擴展性或好的用戶體驗這個獨有問題。

?

架構

?

Modules

Core

Orchard Framework

ASP.NET MVC

NHibernate

Autofac

Castle

.NET

ASP.NET

IIS or Windows Azure

?

Orchard基礎

Orchard CMS基于一些現有的框架和類庫完成。下面列出的是其中一些最根本的組成。

  • ASP.NET MVC: ASP.NET MVC是一個流行的Web開發框架,其鼓勵關注點分離。

  • NHibernate: NHibernate是一個ORM工具。其負責將Orchard內容項的持久化到數據庫并且將模塊開發中對持久化的關注完全移除從而大大簡化數據模塊。可以在任意核心內容類型的源碼(如Pages類)中,看到NHibernate的例子。

  • Autofac: Autofac是一個IoC容器。Orchard對于依賴注入有著重度依賴。創建一個可以注入的Orchard依賴只需編寫一個繼承自IDependency接口(或一個繼承自IDependency更具體話的接口)的類型就可以。使用這個依賴只需要將恰當的類型作為構造函數的參數傳入即可。Orchard將管理被注入的依賴對象的作用域和生存期。IAuthorizationService、RolesBasedAuthorizationService和XmlRpcHandler的代碼是可以作為參考的例子。

  • Castle Dynamic Proxy: Castle被用于動態代理生成。

Orchard應用和框架在這些基礎框架之上構建,作為附加的抽象層。有多種方式實現這些基礎功能,使用Orchard也不需要了解NHibernate, Castle或 Autofac的實現細節。(這句話原文很抽象啊,就這么一翻譯不一定對)

?

Orchard Framework

Orchard Framework是Orchard中最底層的部分。其包含應用的引擎或者說至少是那些不能被獨立到一個模塊的部分。它們是幾乎大部分基礎模塊都需要依賴的最一般化的部分。你可以把它看作Orchard的基礎類庫。

?

啟動Orchard

當一個Orchard Web應用開始運轉,一個Orchard Host被創建。這個Host在應用程序域層級是單例的。

下一步,Host將使用ShellContextFactory為當前"租戶"(tenant)獲取Shell。"租戶"是運行于相同appdomain中相互獨立的應用程序實例,用于提高站點密度。這是用戶可以區分的最上層的存在。Shell在"租戶"這一級是單例的,可以被實際上用來代表"租戶"。Shell對象高效的提供"租戶"層的隔離同時讓"多租戶"對模塊化編程模型透明。

Shell創建后將由ExtensionManager中取得可用擴展的列表。Extensions是模塊和主題。默認實現下將掃描模塊和主題目錄用來找到擴展。

同時,Shell由ShellSettingsManager取得用于"租戶"的設置列表。默認實現是由Appdata中合適的子目錄下獲取設置,但也可以由其他位置獲取這些設置。如,Azure版本的實現中設置存儲在blob storage中,因為Azure環境下Appdata不一定是可寫的。

接著Shell由當前host可用的擴展列表和當前"租戶"的設置中獲取CompositionStrategy對象并用它來準備IoC容器。這個操作的結果不是用于Shell的IoC容器,而是一個ShellBlueprint。其由依賴列表,控制器和記錄藍圖(record blueprint)組成。

隨后每個租戶的ShellSettings及ShellBluePrint被傳入ShellContainerFactory的CreateContainer方法并得到一個ILifetimeScope。這個ILifetimeScope基本上使IoC容器的作用域被限制在租戶一級,這樣模塊可以直接在當前租戶的作用域內獲得注入的依賴而無需其他特殊操作。

?

依賴注入

Orchard中創建可注入依賴的標準方式是創建一個繼承自IDependency或其它繼承自IDependency接口的接口并實現這個接口。在使用方面來看,只需在構造函數中聲明一個接口類型的形參。應用框架會自動發現所有依賴并按需要初始化實例并注入到構造函數中。

有三種不同的作用域可用于注冊依賴,通過繼承自不同的接口就可以在三種中選擇其一。

Request: 一個依賴對象將在每次HTTP請求到來時被創建并在請求被處理完成后銷毀。使你的接口繼承自IDependency接口就是選擇了這種作用域范圍。這個對象的創建應當相當輕量。

Object: 每一次獲取接口的依賴時將會創建一個新的依賴實例。實例從不被共享。使用這種方式,需要讓接口繼承自ITransientDependency。這個依賴對象的創建必須極為輕量。

Shell: 對于每個shell/租戶只有一個實例被創建。要使用這種方式,需要讓接口繼承自ISingletonDependency。只有當需要為Shell的生命周期維持一個一致的狀態才使用這種對象。

?

替換已存在的依賴

可以通過OrchardSuppressDependency特性來修飾類從而替換已存在的依賴,這個Attribute接收一個完整的類型名作為參數,其表示要替換的對象的類型。

?

依賴排序

有些依賴不是唯一的,相反是列表的一部分。如,handler在同一時間都是活動的。有些情況下你希望修改依賴被獲取的順序。可以通過修改模塊的清單(mainfest)中Feature部分的Priority屬性來實現。見下面的例子:

Features:

? ?Orchard.Widgets.PageLayerHinting:

? ? ? ?Name: Page Layer Hinting

? ? ? ?Description: ...

? ? ? ?Dependencies: Orchard.Widgets

? ? ? ?Category: Widget

? ? ? ?Priority: -1

?

ASP.NET MVC

Orchard構建于ASP.NET MVC之上,但為了添加如主題和租戶隔離等支持,Orchard需要引入一個附加的間接層,其將作用在ASP.NET MVC端它需要的概念上,另外也作用于Orchard按Orchard概念等級劃分其中的組成部分。

例如,當請求一個指定視圖時,我們的LayoutAwareViewEngine將作為替代參與這一過程。嚴格來講,這不是一個新的視圖引擎,因為其不關心實際渲染,但其包含找到當前主題對應的恰當視圖的邏輯,然后將渲染工作委托給實際的視圖引擎。

類似的,我們也有Route Provider,Model Binder和控制器工廠類,它們都扮演ASP..NET MVC單一入口的角色并負責將請求轉發給底層恰當作用域中的對象。

以路由為例,我們可能有n個路由提供程序(一般來自于各模塊)以及一個Route Publisher與ASP.NET MVC進行交互。Model Binder和控制器工程的情況也類似。

內容類型系統

Orchard中的內容被一個實際的類型系統所管理,這個系統比底層.NET的類型系統功能更豐富且更動態,從而可以提供更供Web CMS系統所需的靈活性。類型必須可以在運行時動態組合并且反映出內容管理的關注點。

?

類型、部件和字段

Orchard可以處理任意數量的內容類型,包括那些站點管理員以無編碼方式動態創建的類型。這些內容類型由內容部件聚合而成,每一個內容部件處理一個單一的關注點。這樣做的原因是許多關注點跨多個內容類型。

例如,一篇博文,一個產品和一段視頻可能都有一個可路由的地址,相關評論及標簽。這樣,可路由地址、評論和標簽分別作為Orchard中一個單獨的內容部件存在。這樣,這些通用的管理模塊可以被開發一次并被應用到任意內容類型,包括那些評論模塊的作者都不知道的內容類型。

部件本身可以有屬性和內容字段。內容部件也可以以與部件相同的方式被復用:一個具體的字段類型往往被用于多個部件和內容類型。部件與字段的不同在于它們所處理的規模和它們的語義。

字段是比部件更精細構成。例如,字段類型可能描述一個電話號碼或一個坐標,而部件一般用來描述一個完整的關注點像評論和標簽。

但是這里重要的不同在于語義方面:如果對象是實現"is a"關系你應該寫一個部件,反之如果對象是"has a"關系應該寫一個字段。

例如,襯衫is a商品,它has aSKU和價格。你不會說襯衫有一個商品或襯衫是一個價格或SKU。

通過這個例子你知道,襯衫這個內容類型由商品部件構成,而商品部件由一個名為"price"的金額字段和一個名為SKU的字符串字段構成。

另一個不同是,對于每一個內容類型其中只有一個特定類型的部件,從"is a"關系的觀點來看這是合理的。而一個部件可以有任意數量的特定類型的字段。另一種解釋方式,部件中的存儲字段的方式就像一個字典,字段的名稱為鍵,字段的類型為值。而文檔類型是一個部件類型的列表(不包含部件的名字)。

另一種在部件和字段間做選擇的方法是:如果你認為用戶對于一個內容類型中的某對象的可能需要多于一個實例,這個對象應該被作為一個字段。

?

內容類型剖析

正如我們所見,一個內容類型由內容部件構成。從代碼角度來看,內容部件一般與下面的概念相關:

  • 一個記錄,部件數據POCO的表現

  • 實際組成是一個模型類,其繼承自ContentPart<T>,其中T是記錄類型

  • Repository,Repository不需要模塊作者來實現,Orchard會使用一個泛型的Repository。

  • 處理器。處理器實現了IContentHandler接口并且由如OnCreated、OnSaved等一系列事件處理器構成。基本上來說,它們在內容項生命周期的每個部分添加鉤子函數來執行一系列任務。在它們的構造函數中可以添加處理來參與內容項的實際構成。在ContentHandler基類有一個Filter集合用來給內容類型添加通用行為。

    如,Orchard提供了一個StorageFilter,可以很簡單聲明一個內容部件的持久化應該怎樣被處理:只需Filters.Add(StorageFilter.For(myPartRepository));,然后Orchard會處理好myPartRepository的數據持久化到數據庫的操作。

    另一個處理器的例子是ActivatingFilter,其負責完成把部件焊接到類型上的實際操作:這樣調用Filters.Add(new ActivatingFilter<BodyAspect>(BlogPostDriver.ContentType.Name));其將正文內容部件添加到博文對象中。

  • 驅動。驅動是更友好、更專門化的處理器(結果肯定是靈活性更低)并且與特定的內容部件類型相關聯(它們繼承自ContentPartDriver<T>,其中T是內容部件類型)。換句話說,處理器不必僅限于一個內容部件類型。驅動可以看作針對一個特定部件的控制器。它們通常構建通過主題引擎被渲染的外觀。

?

內容管理器

所有Orchard中的內容都通過ContentManager對象來訪問,這是為什么你可以使用你之前并不知道類型的內容的原因。

ContentManager提供方法查詢內容存儲,管理內容版本以及管理內容發布狀態。

?

事務

Orchard針對每個HTTP請求自動創建一個事務。這意味著一個請求中發生的所有操作都是一個“包圍”事務的一部分。如果請求過程中有代碼終止事務,所有數據操作都將被回滾。相反,如果事務從未被顯式取消,在請求的最后所有操作將被提交而無需顯式提交。

?

請求生命周期

這一小節,我們將以請求一篇指定的博文作為例子。

當對一篇特定博文的請求到達時,程序首先查找由各種模塊提供的可用路由,在其中找到博客模塊匹配的路由。這個路由可以解析對博文控制器中item操作的請求,后者將由內容管理器中查找博文。然后基于請求的主要目標由內容管理器中獲得一個Page Object Model (POM)(通過調用 BuildDisplay方法),這樣博文就被由內容管理器中檢索出來了。

博文有其自己的控制器,但對于所有的內容類型不一定如此。如,動態內容類型通過更通用的來自Core Routable部分的ItemController被處理。ItemController中的Display操作完成和博文控制器中幾乎同樣的的事情:由內容管理器中獲取內容項然后用其生成一個POM。

接著布局視圖引擎將根據當前的主題并使用模型類型結合Orchard對視圖命名的約定來解析得到恰當的視圖。

在視圖內部,可能發生如區域定義這樣更動態的形態構造。

實際渲染由樣式引擎來完成,其查找對應的模板或產生外觀的方法(shape method)來以出現順序遞歸的繪制POM出現的每一個“形狀(shape)”

?

小工具

小工具是擁有Widget內容部件和Widget版型的內容類型。如同其他內容類型一樣,小工具也是由部件和字段組成。這意味著它們可以和其他內容類型使用相同的編輯方式和渲染邏輯。它們同樣共享相同的生成模塊,這意味著人惡化已存在的內容部件都可能被作為小部件的一部分使用而幾乎不需要改動成本。

小工具通過小工具層被添加到頁面。層是一系列小工具。層有一個名字,一套決定它們應該出現在站點中的哪些頁面上的規則,一個定義小工具及小工具相關繪制區域位置和排序的列表以及設置。

每個層中附加的規則使用IronRuby表達式來表示。這些表達式可以使用程序中任何IRuleProvider的實現。Orchard附帶了2個開箱即用的實現:url和認證。

?

站點設置

Orchard中站點是一個內容項,其可以讓模塊來焊接附加部件。通過這種方式模塊來提供站點設置功能。

站點設置是租戶隔離的。

?

事件總線

Orchard及其模塊通過創建用于依賴的接口來公開擴展點,這些接口的實現可以被注入。

實現針對擴展點的插件既可以通過實現擴展點接口完成,也可以通過實現一個具有相同名稱和相同方法的接口來完成。換句話說,Orchard不要求嚴格的強類型接口一致,這樣插件可以擴展一個擴展點而無需對聲明擴展點接口的程序集產生依賴。

這正是Orchard事件總線的一個實現。當一個擴展點調用注入的實現,一個消息被發布到事件總線上。監聽事件總線的對象之一將消息分發到繼承自名稱一致的接口的類的方法中。

?

命令

Orchard站點上的許多操作既可以通過命令行來執行也可以通過管理界面來執行。這些命令是通過實現ICommandHandler的類型中使用CommandName特性裝飾的方法來公開的。

Orchard命令行工具通過模擬web站點環境以及通過反射檢查程序集的方式在運行時發現可用的命令。這個命令運行的環境與實際運行站點的環境盡可能的接近。

?

搜索與索引

默認情況下,搜索和索引使用Lucene實現,默認實現也可以被替換為其它索引引擎。

?

緩存

Orchard中緩存依賴于ASP.NET緩存,但我們也公開一個可以通過調用ICache類型依賴對象中Get方法來使用幫助API。Get方法接收一個鍵和一個用于在緩存還沒包含請求項時生成緩存項值的函數。

使用Orchard緩存API的主要好處是它是租戶透明的。

?

文件系統

Orchard文件系統是抽象的,存儲可以根據環境被定向到物理文件系統或如Azure Blob Storage這樣的外部存儲。Media模塊是使用抽象文件系統的一個例子。

?

用戶和角色

Orchard中User是內容項(雖然不是可被路由的),這使它很易于用來構建資料模塊,例如可以使用附加字段來擴展它。Role作為內容部件被焊接到User上。

?

權限

每個模塊可以公開一套權限以及默認情況下這些權限應怎樣被授予Orchard的默認角色。

?

任務

模塊可以通過調用IScheduledTaskManager類型依賴對象上的CreateTask方法來安排一個任務。任務可以通過實現IScheduledTaskHandler來被執行。Process方法可以檢查任務類型名稱并決定怎樣處理它。

任務運行于來自ASP.NET線程池的一個單獨線程上。

?

通知

模塊可以通過調用INotifier類型依賴對象上的方法來將消息顯示到管理界面上。一個請求中可以創建多個通知作為請求的一部分。

?

本地化

應用程序及其模塊的本地化通過調用T方法并傳入字符串資源來完成:@T("This string can be localized")。查看使用本地化幫助函數獲得更多細節和指導。Orchard資源管理器可以由位于應用程序指定位置的PO文件加載本地化資源字符串。

內容項的本地化通過一個不同的機制來實現:內容項的本地化版本是物理上獨立的內容,并且通過一個專用的部件相連接。

當前使用的文化由文化管理器決定。默認實現是返回站點設置中配置的文化,另外可替換的一個實現是由用戶檔案或瀏覽器設置中獲取。

?

日志

日志通過ILogger類型依賴的對象實現。不同的實現可以將日志項發送到不同的存儲類型。Orchard的實現使用了Castle.Core.Logging進行日志。

?

Orchard核心

Orchard.Core程序集包含了一系列Orchard運行必須的模塊。其它模塊可以安全的依賴這些永遠可用的模塊。

核心模塊的例子如訂閱,導航以及路由。

?

模塊

Orchard默認分發版本包含了大量內置的模塊,如博客以及頁面,同時許多第三方模塊也在被開發。

模塊就是一個ASP.NET MVC區域以及一個用于擴展Orchard的manifest.txt文件。

一個模塊一般包含事件處理器,內容類型以及它們默認的呈現模版包括一些管理界面。

當模塊項目的csproj文件被改動或csproj文件關聯的文件被改動時,模塊可以由源代碼被動態編譯。這帶來了一種"記事本"開發方式,即不需要開發者顯式執行編譯,甚至使用如Visual Studio這樣的IDE。

模塊必須被放置到Modules文件夾(Orchard.Web/Modules/MyModule)且文件夾名稱必須與項目產生的編譯后的DLL的名稱匹配。所以,如果你有一個名為My.Custom.Module.csproj的自定義模塊項目,這個項目編譯產生My.Custom.Module.dll,這樣模塊根目錄必須被命名為My.Custom.Module。[~/Modules/My.Custom.Module/]

?

主題

Orchard中一個基本的設計原則是Orchard生成的所有HTML,包括模塊產生的標記可以被主題中的內容所替換。約定定義了那個文件應該進入主題文件層次的哪個位置。

Orchard中整個渲染機制都是建立于形狀(shape)之上。主題引擎的工作就是找到當前的主題并讓主題決定繪制每個形狀的最佳方式。每個形狀都有一個默認的渲染方式,可能來自模塊定義的視圖文件夾中的一個模板,也可能是一段繪制形狀的方法代碼。默認的渲染方式可能被當前的主題覆蓋。主題通過自身的渲染形狀的模板或繪制形狀的代碼來代替默認的從而實現覆蓋。

主題可以擁有父級,這樣子主題可以專門針對父主題的一部分或改造父主題的一部分。Orchard中有一個名為Theme Machine的基礎樣式,其已經過設計可以輕松的用于作為父主題。

主題可以像模塊那樣包含代碼:它們可以有自己的csproj文件同樣也能享受到動態編譯的好處。這樣主題可以定義自己的形狀繪制方法,而且也可以像管理界面添加它們所有的任何設置項。

當前主題的選擇通過實現IThemeSelector的類實現,這個類的方法對所有請求返回一個主題名稱和優先級。這樣可以有多個選擇器對主題的選擇提供選項。Orchard默認帶有四種IThemeSelector的實現:

  • SiteThemeSelector返回當前針對租戶或站點配置的主題,優先級低。

  • AdminThemeSelector在當前URL為管理URL時接管并返回管理主題,優先級高。

  • PreviewThemeSelector使用正在被預覽的主題覆蓋站點當前主題,當且僅當當前用戶是開啟主題預覽的用戶。

  • SafeModeThemeSelector是應用在“安全模式”中時唯一可用的選擇器,安全模式一般出現在程序配置期間。這個選擇器優先級極低。

主題選擇器的一個例子是,當用戶代理被識別為屬于一個移動設備時更換一套移動主題。

?

原文版權歸Orchard基金會團隊,由hystar翻譯,轉載請保留鏈接。

?

轉載于:https://www.cnblogs.com/lsxqw2004/p/4788303.html

總結

以上是生活随笔為你收集整理的[翻译]Orchard如何工作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。