1

我正在開發一個小系統,我開發了經典的通用庫。目前,我的DAL具有以下架構。在需要時,從接口投射到某個具體類是否是一種很好的做法?

public interface IRepositorio<T> where T : class 
{ 
    T Get(long id); 
    long Insert(T obj); 
    bool Update(T obj); 
    bool Delete(T obj); 
} 

public abstract class Repositorio<T> : IRepositorio<T> where T : class 
{ 
    public IDbConnection Connection 
    { 
     get 
     { 
      return new SqlConnection(ConfigurationManager.ConnectionStrings["DBFila"].ConnectionString); 
     } 
    } 

    public T Get(long id) 
    { 
     //... 
    } 

    public long Insert(T obj) 
    { 
     //... 
    } 

    public bool Update(T obj) 
    { 
     //... 
    } 

    public bool Delete(T obj) 
    { 
     //... 
    } 
} 

我的具體資料庫看起來是這樣的:

public class FilaRepositorio : Repositorio<FilaRepositorio> 
{ 
    public FilaRepositorio() 
    { 
    } 

    public void SomeCustomMethod() 
    { 
     // Some custom method 
    } 
} 

我也是用簡單的注射器遵循國際奧委會和DI模式,因爲這個原因,當我嘗試調用「SomeCustomMethod()」我(顯然)沒有訪問權限。看:

public class Processador 
{ 
    private IRepositorio<FilaModel> _repoFila; 
    public Processador(IRepositorio<FilaModel> repoFila) 
    { 
     _repoFila = repoFila; 
    } 

    public void Processar() 
    { 
     _repoFila.SomeCustomMethod(); // <-- wrong 

     ((FilaRepositorio)_repoFila).SomeCustomMethod();// <-- works 
    } 
} 

有鑑於此,我有一些問題:

  • 是個好或可接受的做法使該投(FilaRepositorio)?
  • 如果不是一個好的做法,該如何爲這種情況編寫好的代碼?
+3

如前所述兩個答案,從界面回實現鑄造是一個壞主意。如果你這樣做,絕對沒有理由再有這個接口。更一般地說,如果你的代碼依賴於一個具體的類型,你就違反了[依賴倒置原則](https://en.wikipedia.org/wiki/Dependency_inversion_principle),它指出類應該依賴於抽象。此外,明確將界面轉換爲這種具體類型違反了[Liskov替代原則](https://en.wikipedia.org/wiki/Liskov_substitution_principle)。 – Steven

+3

海事組織,我不認爲這個問題是「主要是基於意見的」,因此它不應該被關閉。文獻和共同設計原則在這方面非常明確,所以這個問題實際上可以通過參考文獻相當客觀地回答(正如我以前的評論中所做的那樣)。 – Steven

回答

3

有幾個選項可用。演員陣容的主要問題在於它是一個實施問題。

如果注入的對象不是FilaRepositorio會發生什麼?

通過進行轉換,您可以將該類緊密耦合到不能保證爲注入依賴關係的實現問題。因此,構造函數並不是完全正確地執行它的功能。

這表明,有必要實行Explicit Dependencies Principle

顯式依賴項原則指出:

方法和類,應明確要求(通常通過 方法參數或構造函數參數)的任何協作對象 他們需要爲了正常運作。

避免它的一種方法是製作一個派生的接口,該接口明確公開其依賴項的所需功能。

public interface IFilaRepositorio : IRepositorio<FilaModel> { 
    void SomeCustomMethod(); 
} 

public class FilaRepositorio : Repositorio<FilaModel>, IFilaRepositorio { 
    public void SomeCustomMethod() { 
     //...other code removed for brevity. 
    } 
} 

並且具有Processador依賴於更有針對性的抽象。

現在根本不需要演員,班級明確表達了自己需要什麼。

public class Processador { 
    private readonly IFilaRepositorio _repoFila; 

    public Processador(IFilaRepositorio repoFila) { 
     _repoFila = repoFila; 
    } 

    public void Processar() { 
     _repoFila.SomeCustomMethod(); // <-- works 
    } 
} 
2

如果你需要從應用程序的任何部分訪問特定方法,那麼具體的方法必須是你的抽象的一部分,否則難保改變具體的類時,你可以使用它。

我不相信你的施法的使用是一個好主意,在所有的,是通常在這種情況下,做的是創造定義,你可以需要使用任何其他方法特定的接口:

public interface IFilaRepositorio : IRepositorio<Fila> 
{ 
    void SomeCustomMethod(); 
} 

而不是使用並宣佈在你的代碼,你認爲你需要使用它的任何部分特定的接口:

public class Processador 
{ 
    private IFilaRepositorio _repoFila; 
    public Processador(IFilaRepositorio repoFila) 
    { 
     _repoFila = repoFila; 
    } 

    public void Processar() 
    { 
     _repoFila.SomeCustomMethod(); 
    } 
} 
+2

而不是像'IFilaRepositorio'接口那樣爲存儲庫創建一對一的接口,還可以看看更多的SOLID方法,比如[this](https://cuttingedge.it/blogs/steven/pivot/entry.php ?id = 91)和[this](https://cuttingedge.it/blogs/steven/pivot/entry.php?id=92)。 – Steven

+0

謝謝@Steven我在S.O.上學到了很多答案。我的下一個問題是:爲每個具體類型創建一個接口是否正確?但我認爲你的評論回答了這個問題。 – Ewerton

+0

@Ewerton這不是一個黑色或白色的答案。應用程序越大,那麼您就越有可能獲得非常常見的概念(如查詢,用例,驗證等),您可以定義這些概念值得他們自己完成概念使用的抽象。所以我會說你通常會重用抽象。這將導致最佳的可維護性 – Steven

相關問題