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

NBearV3 IoC 基礎教學:Web 應用服務定義、Castle 容器配置與依賴注入實戰

     編輯:關於.NET

教學目標

掌握 NBearV3 IoC 模組基本開發流程,包含實體設計、服務介面定義、實作類別、Castle 容器配置與服務調用。

專案結構建立

  1. 空白方案 + 4 個專案:
    EntityDesigns(設計實體)、Entities(生成實體)、ServiceInterfaces(服務介面)、ServiceImpls(服務實作)
    + 1 個 website (ASP.NET Web 應用)
  2. 刪除預設 Class1.cs

Step 1:從現有資料庫生成設計實體

  1. 執行 NBear.Tools.DbToEntityDesign.exe
  2. 連線字串:Server=(local);Database=Northwind;Uid=sa;Pwd=sa
  3. 選擇 Tables:Categories, Products;Views:Products by Category
  4. 點擊 Generate Entities Design → 複製程式碼

Step 2:修飾設計實體

加入 MappingName 與關聯屬性

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

    [FkQuery("Category", OrderBy="{ProductName}", Contained=true, LazyLoad=true)]
    Product[] Products { get; set; }
}

[MappingName("Products")]
public interface Product : Entity {
    [PrimaryKey] int ProductID { get; }
    [SqlType("nvarchar(40)")] string ProductName { get; set; }
    int SupplierID { get; set; }
    int CategoryID { get; set; }
    [SqlType("nvarchar(20)")] string QuantityPerUnit { get; set; }
    decimal UnitPrice { get; set; }
    short UnitsInStock { get; set; }
    short UnitsOnOrder { get; set; }
    short ReorderLevel { get; set; }
    bool Discontinued { get; set; }

    [FkReverseQuery(LazyLoad=false)]
    [MappingName("CategoryID")]
    Category Category { get; set; }
}

[ReadOnly]
[MappingName("Products by Category")]
public interface ProductsByCategory : Entity {
    [SqlType("nvarchar(15)")] string CategoryName { get; }
    [SqlType("nvarchar(40)")] string ProductName { get; }
    [SqlType("nvarchar(20)")] string QuantityPerUnit { get; }
    short UnitsInStock { get; }
    bool Discontinued { get; }
}

注意: 循環關聯時勿同時設 LazyLoad=false,否則導致死循環。

Step 3:生成實體程式碼與配置

  1. 編譯 EntityDesigns
  2. 執行 EntityDesignToEntity.exe 載入 DLL
  3. Generate Entities → Entities\Entities.cs(加入 NBear.Common.dll 參考)
  4. Generate Configuration → website\EntityConfig.xml

Step 4:Gateway 存取資料庫(非 IoC 方式)

Web.config 配置

<configSections>
  <section name="entityConfig" type="NBear.Common.EntityConfigurationSection, NBear.Common" />
</configSections>
<entityConfig>
  <includes> <add key="Sample Entity Config" value="~/EntityConfig.xml" /> </includes>
</entityConfig>
<connectionStrings>
  <add name="Northwind" connectionString="Server=(local);Database=Northwind;Uid=sa;Pwd=sa" providerName="NBear.Data.SqlServer.SqlDbProvider" />
</connectionStrings>

程式碼存取

Gateway gateway = new Gateway("Northwind");
Category[] categories = gateway.FindArray<Category>(WhereClip.All, OrderByClip.Default);

Step 5:定義服務介面與實作

ServiceInterfaces 專案(參考 NBear.Common.dll, NBear.IoC.dll, Entities)

public interface ICategoryService : IService {
    Category[] GetAllCategories();
    Category GetCategoryByID(int categoryID);
}

public interface IProductService : IService {
    Product[] GetAllProducts();
    Product GetProductByID(int productID);
}

服務介面必須繼承 IService。

ServiceImpls 專案(參考 Entities, ServiceInterfaces, NBear.Common/Data/IoC)

public class CategoryService : ICategoryService {
    public Category[] GetAllCategories() {
        return Gateway.Default.FindArray<Category>(WhereClip.All, OrderByClip.Default);
    }
    public Category GetCategoryByID(int categoryID) {
        return Gateway.Default.Find<Category>(categoryID);
    }
}

public class ProductService : IProductService {
    public Product[] GetAllProducts() {
        return Gateway.Default.FindArray<Product>(WhereClip.All, OrderByClip.Default);
    }
    public Product GetProductByID(int productID) {
        return Gateway.Default.Find<Product>(productID);
    }
}

Step 6:Castle 容器配置與服務調用

Web.config 加入 castle 區段

<configSections>
  <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
  <section name="entityConfig" ... />
</configSections>
<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>

Default.aspx.cs 調用服務

protected void Page_Load(object sender, EventArgs e) {
    ServiceFactory factory = ServiceFactory.Create();
    
    IProductService ps = factory.GetService<IProductService>();
    Product[] products = ps.GetAllProducts();
    WriteLine($"Got all products, {products.Length} in total.");
    
    ICategoryService cs = factory.GetService<ICategoryService>();
    Category[] categories = cs.GetAllCategories();
    WriteLine($"Got all categories, {categories.Length} in total.");
    
    foreach (Category item in categories) {
        WriteLine($"ID={item.CategoryID}, Name={item.CategoryName}, Products in category: {item.Products.Length}.");
    }
}

關鍵概念:ServiceFactory 單例模式

ServiceFactory.Create() 內部為單例,隨處呼叫皆取得同一實例。服務實作間互相調用時,只需引用 ServiceInterfaces,避免實作相依,耦合度降至最低。

部署注意

Website 不需參考 ServiceImpls,但需將 ServiceImpls.dll 複製至 Website 的 Bin 目錄,供 Castle 容器動態載入。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved