首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

NBearV3 IoC 進階教學:分散式 Web 應用開發、實體序列化避坑與服務部署實戰

     編輯:關於.NET

教學目標

掌握使用 NBearV3 IoC 模組開發單機/分散式應用的完整流程,理解分散式系統中實體定義與服務介面設計的關鍵注意事項。

核心架構原理

NBearV3 分散式支援基於 ServiceMQ Server 訊息中心,使用 .NET Remoting 傳遞訊息,Castle Windsor 作為 IoC 容器。用戶端透過定義本地服務介面與實作、配置部署,即可在不修改程式碼甚至不重新編譯情況下賦予應用分散式能力,支援以 Service 為單位多伺服器部署與自動負載平衡。

Step 1:環境準備

  1. 下載 NBearV3 最新版(SourceForge)
  2. 解壓至 C:\,取用 dist 目錄 DLL/EXE 與 tutorials\IoC_Tutorial 基礎專案
  3. 複製 IoC_Tutorial 專案重命名為 IoC_Adv_Tutorial

Step 2:實體設計規範——避免循環序列化

問題:雙向可讀寫屬性導致序列化死循環

Category 與 Product 互相參考(Category.Products、Product.Category)。分散式呼叫時參數/回傳值會序列化傳遞,導致無限遞迴:Product → Category → Products → Product...。

解決方案:單向可讀或標記忽略序列化

[MappingName("Categories")]
public interface Category : Entity {
    [PrimaryKey] int CategoryID { get; }
    string CategoryName { get; set; }
    string Description { get; set; }
    byte[] Picture { get; set; }

    [FkQuery("Category", OrderBy = "{ProductName}", Contained = true, LazyLoad = true)]
    [SerializationIgnore]  // 關鍵:忽略序列化
    Product[] Products { get; set; }
}

將 Category.Products 設為 [SerializationIgnore] 或唯讀(只有 get),即可打破循環。

Step 3:程式碼生成

  1. 編譯 EntityDesigns 專案
  2. 執行 NBear.Tools.EntityDesignToEntity.exe 載入 DLL
  3. 點擊 Generate Entities → 儲存至 Entities\Entities.cs
  4. 點擊 Generate Configuration → 儲存至 website\EntityConfig.xml

Step 4:分散式部署架構

目錄結構

IoC_Adv_Tutorial\Bin\
  ├─ ServiceMQServer\  (NBear.IoC.Servers.ServiceMQServer.exe + 相關 DLL)
  └─ ServiceHost\      (ServiceHost.exe + 服務介面/實作/實體 DLL + 相關 DLL)

ServiceMQServer 設定檔

<configuration>
  <configSections>
    <section name="serviceFactory" type="NBear.IoC.Service.Configuration.ServiceFactoryConfigurationSection, NBear.IoC" />
  </configSections>
  <serviceFactory type="Remoting" name="testServiceFactory" protocol="HTTP" server="127.0.0.1" port="8888" debug="true" maxTry="30" />
</configuration>

關鍵:type="Remoting" 啟用遠端連線,預設 Local 無法連線遠端。

ServiceHost 設定檔

<configuration>
  <configSections> ... </configSections>
  <entityConfig> <includes> <add key="Sample Entity Config" value="~/EntityConfig.xml" /> </includes> </entityConfig>
  <castle>
    <components>
      <component id="category service" service="ServiceInterfaces.ICategoryService, ServiceInterfaces" type="ServiceImpls.CategoryService, ServiceImpls" />
      <component id="product service" service="ServiceInterfaces.IProductService, ServiceInterfaces" type="ServiceImpls.ProductService, ServiceImpls" />
    </components>
  </castle>
  <serviceFactory type="Remoting" name="testServiceFactory" protocol="HTTP" server="127.0.0.1" port="8888" debug="true" maxTry="30" />
  <connectionStrings> ... </connectionStrings>
</configuration>

ServiceHost 需完整配置實體、Castle 元件、連線字串,因其需直接存取資料庫執行服務邏輯。

Website 客戶端設定檔(混合本地/遠端服務)

<castle>
  <components>
    <component id="category service" service="ServiceInterfaces.ICategoryService, ServiceInterfaces" type="ServiceImpls.CategoryService, ServiceImpls" />
    <!-- 保留本地 category service,移除 product service 強制走遠端 -->
  </components>
</castle>
<serviceFactory type="Remoting" name="testServiceFactory" protocol="HTTP" server="127.0.0.1" port="8888" debug="true" maxTry="30" />

Step 5:執行驗證

  1. 啟動 ServiceMQServer.exe
  2. 啟動多個 ServiceHost.exe 實例(觀察訂閱日誌)
  3. 執行 Website,重新整理頁面觀察負載平衡:IProductService 請求分配至不同 ServiceHost
  4. 註解 Web.config 本地 category service 後,ICategoryService 也會走遠端

重要補充說明

LazyLoad=true 屬性在分散式傳遞後的行為

實體序列化時已觸發屬性存取,遠端接收的實體 LazyLoad 屬性實際已載入,存取時直接回傳記憶體資料。

ServiceFactory 動態代理原理

  1. 優先檢查本地 Castle 配置,有則直接 new 實例
  2. 無本地實作時,用 System.Reflection.Emit 動態建立代理類別(快取復用)
  3. 代理類別序列化參數 → 封裝 RequestMessage → 送 ServiceMQServer
  4. ServiceMQServer 負載平衡轉發至可用 ServiceHost
  5. ServiceHost 執行邏輯 → 回傳結果 → 代理類別反序列化 → 回呼端

自訂序列化與自訂 Server/Host

  • SerializationManager.RegisterSerializeHandler() 註冊特定型別自訂序列化/反序列化
  • 官方 ServiceMQServer/ServiceHost 為簡易 Console 程式,實務建議改寫為 Windows Service 或 WinForm
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved