2011-08-03 34 views
9

我從MVC3開始,希望使用一些靈活的體系結構,因此我已經閱讀了數十篇博客,一本書(Pro ASP.NET MVC 3),閱讀了SOLID原則,並最終得到了應用程序的結構,我喜歡(或至少我是這麼認爲的,到目前爲止,因爲我還沒有建立在它做任何事):在SOLID應用程序體系結構中使用Ninject

enter image description here

在這種結構中:

  • 域名持有POCO類別並定義服務接口
  • 服務實現的服務接口和定義庫接口
  • 數據實現倉庫接口
  • WebUI和域名使用服務
  • 服務使用存儲庫
  • WebUI中,服務和數據依賴於域POCO類

域使用服務的主要原因是驗證POCO(IValidatable)類的Validate方法上的唯一鍵。

我開始構建具有這種結構的參考應用程序,但我已經遇到,到目前爲止,兩個問題:

  1. 我使用的是Data.Tests項目,單元測試的存儲庫,但還沒有找到一種方法在模型上注入(使用Ninject)服務的實現(在構造函數中或其他方面),所以Validate方法可以調用服務上的CheckUniqueKey。

  2. 我還沒有找到任何有關將Ninject連接到TEST項目(大量用於WebUI項目)的參考。

我在這裏想要的是beeing能夠從EF切換到DAPPER之類的其他東西,只需更改DATA組件即可。

UPDATE

現在(如09-AUG-2011)Ninject是工作,但我覺得我失去了一些東西。

我有兩個構造一個CustomerRepository:

public class CustomerRepository : BaseRepository<Customer>, ICustomerRepository 
{ 
    // The repository usually receives a DbContext 
    public CustomerRepository(RefAppContext context) 
     : base(context) 
    { 
    } 

    // If we don't receive a DbContext then we create the repository with a defaulte one 
    public CustomerRepository() 
     : base(RefApp.DbContext()) 
    { 
    } 

    ... 
} 

在TestInitialize:

// These are for testing the Repository against a test database 

[TestInitialize()] 
public void TestInitialize() 
{ 
    // Context used for tests 
    this.context = new RefAppContext(); 

    // This is just to make sure Ninject is working, 
    // would have used: repository = new CustomerRepository(context); 

    this.kernel = NinjectMVC3.CreateKernel(); 

    this.kernel.Rebind<ICustomerRepository>().To<CustomerRepository>().WithConstructorArgument("context", context); 

    this.repository = kernel.Get<ICustomerRepository>(); 

} 

Customer類:

public class Customer : IValidatableObject 
{ 
    ... 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     // I want to replace this with a "magic" call to ninject 
     CustomerRepository rep = new CustomerRepository(); 

     Customer customer = rep.GetDupReferenceCustomer(this); 

     if (customer != null) 
      yield return new ValidationResult("Customer \"" + customer.Name + "\" has the same reference, can't duplicate", new [] { "Reference" }); 
    } 

    ... 
} 

什麼是用最好的方式Ninject在這種情況下?

任何幫助將不勝感激。

回答,有點

因爲到目前爲止aswered我會考慮這個問題。我可以讓Ninject工作,有點像,但是看起來像SOLID的依賴倒置原則(DIP)需要更多的時間。

在這方面,我不得不將域,服務和數據合併在一起,我會在其他時間創建另一個問題,並保持項目按現在的常規方式。

謝謝大家。

+1

建議取出Ninject參考並將其更改爲DI,因爲答案不會(並且不應該根據您的特定容器進行更改)。我也會添加一個架構或找到更多的標籤。 –

+0

@Ruben你是對的,在同一句話中使用「Ninject」和「應用程序體系結構」聽起來不太合適,只是在這種情況下,我試圖解決一個非常特定於Ninject的問題。 –

+1

我會將更新放入一個新的問題,因爲它是一個完全不同於第一個問題的其他主題。否則很多人都不會閱讀你的新問題。 –

回答

3

單元測試應該在沒有Ninject的情況下完成。只需創建一個正在測試的對象的實例並手動爲每個依賴注入一個模擬。

對於集成測試,您可以使用內核包含來自應用程序引導程序的所有綁定,並使用模擬替換所有您想要替換的內容。例如將Session綁定替換爲使用內存數據存儲而不是實際數據庫的綁定。

+0

現在我正在進行集成測試,因爲我正在測試訪問實際數據庫的存儲庫。 Ninject的使用是最終能夠用其他方式替換服務層。在這種情況下,POCO.Validate方法使用在接口中定義的Service方法。重點是,例如如何解決Customer.Validate方法中的服務接口,以便我可以使用CustomerServices.FindCustomerByEmail(電子郵件)方法檢查是否有另一個客戶使用同一封電子郵件。 –

+0

@Miguel Veloso:更新集成測試 –

+0

我應該在哪裏放置應用程序引導程序?測試項目中沒有Global.asax! –