2012-01-12 90 views
2

我正在處理一個服務,它通過一個存儲庫執行數據庫操作。在服務中,我實例化需要構造函數中的數據庫上下文的存儲庫。我想知道上下文是否應該傳入服務中,或者下面的代碼是否正確。或者是否最好將Repository對象傳遞給它使用的服務?在使用Service類時,UI代碼應該是什麼樣子?創建通過存儲庫執行數據庫調用的服務的正確方法是什麼?

public class Service 
    { 
     private IRepository<WWW> _repository; 

     public Service() 
     { 
      _repository = new Repository<WWW>(new DBContext()); 
     } 

     public WWW GetWWW(int wwwID) 
     { 
      return _repository.Get(x => x.WWWID == wwwID).FirstOrDefault(); 
     } 

     public void AddWWW(WWW www) 
     { 
      _repository.Add(www); 
     } 

     public void DeleteWWWByID(int wwwID) 
     { 
      _repository.Delete(x => x.WWWID == wwwID); 
     } 

     public void SaveChanges() 
     { 
      _repository.SaveChanges(); 
     } 
    } 

回答

2

事實上,倒不如通過服務的構造函數傳遞一個信息庫的服務,像這樣:

public class Service 
{ 
    private readonly IRepository<WWW> _repository; 

    public Service(IRepository<WWW> repository) 
    { 
     _repository = repository; 
    } 

    /* the rest is unchanged */ 
} 

Tipically,代表UI將採取服務依賴的類,所以代碼可能是這樣的:

public class UIClass : BaseClassDictatedByCurrentUIFramework 
{ 
    private readonly Service _service; 

    public UIClass(Service service) 
    { 
     _service = service; 
    } 

    /* UI code that will eventually call methods on the service */ 
} 

你下一步要做的是配置控制容器的反轉,這將知道如何解決餵養日IRepository的實例(和em適當的DataContext實例,如果需要的話)。

例如,如果我們的UI代碼是MVC3控制器,我們會告訴容器解析此控制器的一個實例。這是發生了什麼:

  • 容器注意到在Service的依賴(構造函數中),並試圖解決它。

  • 由於Service是一個具體的類,容器將試圖解決它,然後 注意到對IRepository<WWW>的依賴關係。

  • IRepository的分辨率,因爲這是一個接口,要求容器先前已經被設置爲「知道」什麼時候被要求返回一個實例。通常,這只是界面和它的具體實現之間的映射。在我們的情況下,具體實施是Repository<WWW>和容器也負責「知道」如何實例所需DataContext實例它(這也必須事先配置)

  • 有一個庫實例,然後將容器能夠正確實例化第一個Service,然後是控制器類。

注意具體類的自動分辨率功能不是所有的IoC容器有;有些需要顯式配置才能這樣做。

除此之外,我認爲Service類在您的情況下不會增加太多價值。它只包含由存儲庫實現的方法的委託。在這種情況下,最好讓UI直接依賴IRepository<WWW>並簡單地刪除Service類。 但是,如果這個Service類只是一個例子,並且在您的真實項目中它實現了實際的業務規則,那麼它應該保留。

更新:如何解決ASP中的依賴關係。Net Webforms

上面介紹的例子是理想的依賴注入場景。例如,在ASP.NET MVC中,BaseClassDictatedByCurrentUIFramework將是Controller - 在這種情況下,框架允許我們控制實例化控制器的組件,因此我們可以在構造函數中注入自己的依賴項。

但是,ASP.Net WebForms不是一個非常友好的框架。它要求每個Page都需要有一個默認構造函數,這使得所有的構造函數注入想法都不合適。

在這種情況下,一個可能的解決方案如下妥協:

  • 實例在應用程序啓動(在Globals.asax)IoC容器,並通過一些全局狀態可用它(例如,應用程序上下文)在Page
  • 聲明依賴爲private readonly領域,但構造不會有相應的參數(這將在根本沒有參數)
  • 在構造函數體:
    • 得到IoC容器的參考(可從全局狀態)
    • 使用容器來解決所有依賴性的類有

請注意,這種方法需要的學科 - 它很容易在構造函數的其他地方使用容器來解析其他組件。這種方法稱爲服務定位器,它被認爲是反模式(http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx),因此應該避免。

+0

感謝您的回覆。在UIClass示例中,這將如何在傳統的ASP.net應用程序中工作? – Jason 2012-01-12 23:04:42

+0

@Jason:我編輯了我的答案,以包含在ASP.NET WebForms中執行依賴注入的一種可能的解決方案。關於這個主題的更高級的話題,我推薦一本好書 - Mark Seemann的「.NET中的依賴注入」 – GolfWolf 2012-01-13 09:18:22

0

我建議加大依賴倒置。就我個人而言,我認爲它不是您是否應該將服務傳遞給DBContext,而是您應該將服務傳遞給Repository本身。

相關問題