2010-11-19 101 views
1

自從我使用接口協方差的最後一個問題以來,我還沒有遇到代碼問題。今天,我採取了另一種方法來OLGAtherer架構,我發現巨大的(對我來說)障礙。我希望它的巨大的只有我,我會找到答案在這裏:) OK,請檢查了這一點:如何指向泛型抽象類?

我有抽象泛型類:

abstract class Repository<T> where T : Entity 

這個類包含四種CRUD方法簽名(加,插入等)和兩個受保護的字段。我將創建的任何存儲庫都必須從此超類繼承。我有一個像倉庫,例如:

class BookRepository : Repository<Book> 

現在我有DB類是負責對DB文件操作。這是我的問題。看看這個方法放在DB類:

void Add(List<Entity> enitites, Type entityType) 
    { 
     Repository<entityType> repo = EntitiesFactory(entityType); 
     repo.Add(entities); 
    } 

我知道,上面的方法都不行,但是這個想象我的問題(希望) - 我想動態地創建指定類型的倉庫,但我有不知道如何做到這一點。這一直是我的主要OOP問題 - 我可以編寫繼承(或接口的實現),但我不能使用這些繼承的類。請向我澄清一下。先謝謝你。

帕維爾


我用你提供的線索,這就是我現在:現在

public void Add<T>(List<T> entities, string repoName) where T : Entity 
{ 
    Repository<T> repo = RepoFactory<T>(repoName, typeof(T)); 
    repo.Add(entities); 
} 

private Repository<T> RepoFactory<T>(string repoName, Type t) where T : Entity 
{ 
    if (t == typeof(Book)) 
    { 
    Repository<T> repo = (Repository<T>)((object)(new BookRepository(this.ConnectionString, repoName))); 
    } 

    return null; 

}

RepoFactory是DB類(這是由方式,在這裏某種橋樑) - 它應該移動到其他地方,但這不是一個主要問題。

首先,我不知道RepoFactory體是否以正確的方式實現 - 我想不是。

第二 - 我假設我會從其他類調用DB方法(比方說 - WindowsForm,爲簡單起見)。我將根據用戶的選擇調用添加參數T.這是我有問題並暫時修復它的情況,因爲現在DB是可以的,但是如果我必須實現WindowsForm代碼,我會再次遇到它(我認爲) - 將來我會試着找出答案同樣的問題,但在更高的層次上(DB以上) - 我希望你明白我... 我基本上是說,我不會知道如何動態調用添加方法,因爲T將取決於用戶的選擇(OLGAtherer有成爲Repository Manager,可以支持書籍和其他類型的集合)。如果用戶嘗試使用他的書集,我將不得不調用Add()方法。如果使用Comics集合,則添加()。我不想爲每種類型的集合編寫類,而是使用Add的一個調用來執行此操作。

如果你明白我的意思,你真的很好:)我的英語很爛,但我正在努力。 感謝您提供以前的答案,並提前感謝您提供更多答案。 Paweł

+1

嗯,我想你想重新發明輪子。爲什麼當你有很多已經很好開發的替代品如NHibernate和Linq2Sql時,你可以編寫自己的ORM? – Juliet 2010-11-19 20:01:20

+0

'DB'聽起來像一個上帝對象,'EntitiesFactory'聽起來像一個服務定位器。你正在爲自己設定一個無法維護的,不可測試的災難。 – jason 2010-11-19 20:49:00

+0

你好,我知道這可能看起來不是一個好主意 - 我仍然在學習,我知道OOP的掌握需要花費數年的時間。但是如果你看看我放在Sourceforge上的代碼,我認爲你會接受我創建的架構。無論如何,謝謝您的回覆。 – skrzeczowas 2010-11-20 20:03:48

回答

7

我不太清楚你想要什麼。這會做什麼?

void Add<T>(List<T> entities) where T : Entity 
{ 
    Repository<T> repo = EntitiesFactory(typeof(T)); 
    repo.Add(entities); 
} 

此外,我建議你儘可能靈活地使用輸入參數,例如,使用IEnumerable<T>而不是List<T>用於此方法以及Repository<T>.Add()方法。您可能想要傳入延遲評估的查詢,或將多個LINQ方法鏈接在一起。

+0

+1正是我要回答的。 – Sorax 2010-11-19 19:54:42

+0

哇。任何時候,我不知道該怎麼做,我無法在任何地方找到答案,我知道我可以在這裏發帖,我一定會得到答案!感謝您的這些以及關於釋放依賴關係的有用提示。我想問你讀下面我的新帖子 - 這個問題的下一部分:)最好的問候,Paweł – skrzeczowas 2010-11-20 20:39:40

3

您可以使Add方法通用。

void Add<T>(List<T> enitites) 
{ 
    Repository<T> repo = EntitiesFactory(typeof(T)); 
    repo.Add(entities); 
} 
+0

是的,這是:) – skrzeczowas 2010-11-20 20:40:01

2

如下你可以把它的類型安全通過一個間接更多層的改你的對象hiearchy:

public abstract class EntityCollection<T> : List<T> 
    where T : Entity 
{ 
    public abstract Repository<T> GetRepository(); 
} 

public class BookCollection : EntityCollection<Book> 
{ 
    public override Repository<Book> GetRepository() 
    { 
     return BookRepository(); 
    } 
} 

所以現在你可以修改你的數據庫類,如下所示:

public void Add<T>(EntityCollection<T> entities) 
{ 
    Repository<T> repo = entities.GetRepository(); 
    repo.Add(entities); 
} 

所以現在您可以將BookCollection的實例傳遞給您的Add方法,並且它將以100%類型安全,透明的方式工作。

+0

我不知道這是否正是你要找的答案,但它更好地保持它類型安全,而不是嚴重依賴鑄件和型式試驗。如果你不得不打開一個泛型類型參數,你做錯了什麼。 – Juliet 2010-11-19 20:13:01

+0

朱麗葉,你說的肯定是對的,但實際上我問了上面的問題,因爲我不知道如何切換。如果你能告訴我該怎麼做不使用開關會很好。 – skrzeczowas 2010-11-20 21:00:58

2

只需添加到其他人的答案中,您也可以查看控制反轉(IoC)設計模式。它可能會在未來的工作中簡化你的生活。例如,使用IoC爲您提供的依賴注入,您可以顯着簡化對EntitiesFactory的使用。

我現在使用StructureMap來實現IoC,它對我來說工作的很好。

Here is Martin Fowler's page on IoC,and Wikipedia's,讓你開始。

+0

謝謝你的回答!我很高興在這裏得到這麼多有用的信息。 – skrzeczowas 2010-11-20 20:44:13

1

無論你回來EntitiesFactory()是你需要使用。所以這個問題真的與你沒有顯示的代碼有關。顯示EntitiesFactory()的代碼,我們可以更好地瞭解您要完成的任務。

注意:您知道您不能重載返回類型(不幸)。

+0

不幸的是,我在上面的Add方法中編寫的代碼是某種「僞代碼」。我的意思是,這是我想如何工作:)請閱讀下面的帖子。無論如何謝謝你的回答。 – skrzeczowas 2010-11-20 21:02:51