原址:http://www.nopcommerce.com/docs/74/frequently-asked-development-questions.aspx
以下是開發者常見問題的清單。也介紹了一些nopCommerce開發團隊的編碼規范。
有什么要求?
nopCommerce技術和系統需求可以在這里找到。
開發者如何為nopCommerce項目做出貢獻?
nopCommerce在Codeplex Mercurial托管了一個源碼庫,用戶可以在這里查看。用戶在公共庫可以看到即將發生變化的設計決策,以及以前的設計決策。想了解更多關於Codeplex Mercurial對版本樹的支持信息請點擊這里.開發人員可以輕松地將其插件或語言包上傳到我們的擴展部分,並與其他用戶共享。要上傳一個擴展信息請在Web瀏覽器中訪問我的帳戶頁面,選擇標有“Your contributions and extensions”選項卡,並單擊“Upload a new extension”按鈕。
如何報告一個BUG?
nopCommerce使用Codeplex作為官方BUG跟蹤系統,如果發現一個BUG,可通過在Codeplex創建一個新的任務來報告給nopCommerce團隊。開發者或用戶也可以在我們的BUG論壇版塊發帖子來告知新發現的BUG。通過這里你有機會驗證你的BUG是否已經被提交,這個很重要。因為BUG的重復提交會浪費時間,減少我們在開發新功能和改其他BUG的時間。
數據訪問層
該Nop.Data項目包含了一系列的類和函數來讀取和寫入數據庫或其他數據存儲介質。該Nop.Data庫有助於將數據訪問的邏輯從業務對象中分離出來(分離關注點)。 NopCommerce使用實體框架(EF)Code-First方法。Code-First允許開發人員在源代碼中定義實體(所有核心實體在Nop.Core項目中定義),然后用EF來生成基於C# 類的數據庫。這就是為什么它被稱為Code-First。然后,您可以使用LINQ來查詢對象,因為它會悄悄地把代碼轉化為SQL語句並在數據庫執行。 NopCommerce采用了流暢的API來完全定制持久性映射。如果想了解更多Code-First請訪問這里或這里。
控制反轉和依賴注入
控制反轉和依賴注入是兩個密不可分的方法,用來分離你應用程序中的關注點。控制反轉Inversion of Control (IoC)意味着一個對象不會新創建一個對象並依賴着它來完成工作.相反,它們從外部獲取它們想要的對象.依賴注入Dependency Injection (DI) 意味着在沒有對象的干預下,一般通過能傳入構造參數和一系列屬性的框架組件完成。Martin Fowler寫過一篇關於依賴注入和控制反轉的文章,我就不再重復了,你可以在這兒找到。NopCommerce使用Autofac類庫作為IOC容器。只要你寫了一個服務和此服務已實現的適當接口,你應該在實現了IDependencyRegistrar接口(Nop.Core.Infrastructure.DependencyManagement 命名空間)的類里注冊它。比如所有nopCommerce的核心服務都在Nop.Web.Framework類庫的DependencyRegistrar類中注冊了。

1 public class DependencyRegistrar : IDependencyRegistrar 2 { 3 public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder) 4 { 5 builder.Register(c => c.Resolve<HttpContextBase>().Request) 6 .As<HttpRequestBase>() 7 .InstancePerHttpRequest(); 8 9 ... 10 } 11 }
你想創建多少依賴注冊類都可以。每一個類實現了IDependencyRegistrar接口的類都有一個Order屬性,可以用它來替換一個現有的依賴。要覆蓋nopcommerce的依賴,設置order屬性大於0。Nopcommerce會對依賴排序,並按順序運行,數字越大你的對象被注冊的時間就會被推后。
如何新建一個新的routes
ASP.NET Routes負責接收傳入的瀏覽器請求並把它映射到特定的MVC控制器Action操作上。在這里可以找到關於此路由的詳細信息。 Nopcommerce有一個叫IRouteProvider的接口,用於在應用程序開始時注冊路由。所有核心路由被注冊在位於Nop.Web項目的RouteProvider類。

1 public partial class RouteProvider : IRouteProvider 2 { 3 public void RegisterRoutes(RouteCollection routes) 4 { 5 //home page 6 routes.MapLocalizedRoute("HomePage", 7 "", 8 new { controller = "Home", action = "Index"}, 9 new[] { "Nop.Web.Controllers" }); 10 } 11 }
你想創建多少RouteProvider都可以。比如你的插件有自定義路由,需要注冊,你可以創建一個實現IRouteProvider接口的新類,再根據插件具體注冊路由。
數據驗證
數據驗證是確保程序的數據操作能干凈、正確和有用的過程。大多數.NET開發人員使用Data Annotation Validators。但nopCommerce使用Fluent Validation。是一個使用fluent接口和lambda表達式來生成業務邏輯驗證規則的.NET小型驗證類庫。在nopCommerce必須以下兩個步驟來添加一個校驗到一些模型中:
1、創建一個從AbstractValidator類派生的類,並把所有必須的驗證邏輯都放入其中,你可以從下面的代碼中得到些啟發:

1 public class AddressValidator : AbstractValidator<AddressModel> 2 { 3 public AddressValidator(ILocalizationService localizationService) 4 { 5 RuleFor(x => x.FirstName) 6 .NotEmpty() 7 .WithMessage(localizationService.GetResource("Address.Fields.FirstName.Required")); 8 } 9 }
2、添加ValidatorAttribute屬性,如下:

1 [Validator(typeof(AddressValidator))] 2 public class AddressModel : BaseNopEntityModel 3 {}
當一個視圖模型被提交到控制器,ASP.NET會執行相應的校驗。
計划任務
有了計划任務,你可以在后台創建一個任務,讓它在指定的時期里運行。比如nopCommerce會定時地發送隊列中的email。任務是在ASP.NET線程池中由單獨的線程執行。創建一個新的任務有如下基本步驟:
- 定義一個實現ITask接口的類。它只有一個不帶參數的方法;執行。當任務啟動的時候,這個方法會被調用。
- 計划任務開始時,應該插入一條新的ScheduleTask記錄到相應的數據庫表。您可以使用IScheduleTaskService來執行插入操作。
事件暴露和處理
事件是把消息廣播給相關部分。事件是由數據改變來觸發的如添加,更新和刪除數據。NopCommerce允許開發者“監聽”事件。開發者要想玩轉事件基本上有如下兩條路走:要么發布某個事件讓其它人來用;要么用別的編好並發布的事件。
- 發布一個事件,必須先取得一個IEventPublisher實例再使用相應的數據一起調用Publish方法。
- 要監聽一個事件,必須實現一個新的IConsumer泛型接口,一旦有人使用這個事件,nopCommerce會用反射來尋找並注冊這個事件的實現。
設置API
和其他網站平台一樣,nopCommerce也有“網店名稱”或“啟用單頁購買”這類設置,在nopCommerce中有兩種辦法來管理設置.
你可以用實現ISettingService接口的方法SetSetting和GetSettingByKey來加載和保存單個設置。而在nopCommerce中最好的處理設置的辦法是創建一個ISettingService接口的新實現。每個設置將變為C#屬性,程序員在需要時應該使用setting類構建函數注入設置。以下是setting類的示例代碼。

1 public class MediaSettings : ISettings 2 { 3 public int AvatarPictureSize { get; set; } 4 public int ProductThumbPictureSize { get; set; } 5 public int ProductDetailsPictureSize { get; set; } 6 public int ProductThumbPictureSizeOnProductDetailsPage { get; set; } 7 public int ProductVariantPictureSize { get; set; } 8 public int CategoryThumbPictureSize { get; set; } 9 public int ManufacturerThumbPictureSize { get; set; } 10 public int CartThumbPictureSize { get; set; } 11 12 public bool DefaultPictureZoomEnabled { get; set; } 13 14 public int MaximumImageSize { get; set; } 15 }