2010-11-19 12 views
1

私はインターフェイスの共分散に関する私の最後の問題以来、コードに問題がありません。今日私はOLGAthererアーキテクチャーにもう一度アプローチしましたが、私にとって大きな障害が見つかりました。汎用抽象クラスを指すには?

を私は抽象ジェネリッククラスがあります:

abstract class Repository<T> where T : Entity 

このクラスは、4つのCRUDメソッドのシグネチャを(追加含んをOK、これをチェックしてみてください:)私は私のためにその巨大なことを願っていますし、私はここで答えています、挿入など)と2つの保護されたフィールド。私が作成するすべてのリポジトリは、このスーパークラスから継承しなければなりません。私は、例えば:

class BookRepository : Repository<Book> 

のようなリポジトリを持っています。DBファイルの操作を担当するDBクラスがあります。そして、私の問題があります。私は動的に指定されたタイプのリポジトリを作成したいと思いますが、私は持っている - 私は上記の方法が機能しないことがわかっているが、これは私の問題を可視化する(できれば)

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

:DBのクラスにこの方法を見てくださいどのようにこれを行うか分かりません。これは常に私の主な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本体が適切な方法で実装されているかどうかわかりません。

2番目 - 他のクラスのDBメソッドを呼び出すことを前提としています(わかりやすくするために - WindowsFormとしましょう)。ユーザーの選択に応じてパラメータTでAddを呼び出します。これは問題があり、一時的に修正する状況ですが、DBは問題ありませんが、WindowsFormコードを実装する必要がある場合は、別の時間に遭遇します(私は思っています)。同じ質問ですが、上のレベル(DBの上) - 私はあなたが私を理解することを願っています... Tはユーザの選択に依存するので、私は動的にAddメソッドを呼び出す方法を知らないということを基本的には意味します(OLGAthererは書籍やその他の種類のコレクションをサポートするリポジトリマネージャになる)。そしてユーザーが彼の本のコレクションで作業しようとするなら、私はAdd()メソッドを呼び出さなければならないでしょう。コミックコレクションの場合、Add()。私はコレクションの種類ごとに上記のクラスを書くのではなく、Addの呼び出しを使用してこれを行います。

あなたが私の言いたいことを理解すれば、あなたは本当に良いです:)私の英語はうんざりですが、私はそれに取り組んでいます。 前回のお返事ありがとうございました。今後のお返事ありがとうございます。 Paweł

+1

ええと、私はあなたが車輪を再発明しようとしていると思います。 NHibernateとLinq2Sqlのような十分に開発された選択肢がたくさんある場合、なぜあなた自身のORMを書くのですか? – Juliet

+0

'DB'はGodオブジェクトのように聞こえ、' EntitiesFactory'はサービスロケータのように聞こえます。あなたは、維持されていない、不確実な災害のために自分自身を設定しています。 – jason

+0

こんにちは、これは良いアイデアのように見えるかもしれないことを知っています - 私はまだ学んでおり、OOPのマスタリングには数年かかるでしょう。しかし、もしあなたが私のコードをSourceforgeに置いてみたら、私がまだ作ったアーキテクチャを受け入れるだろうと思っています。とにかくお返事ありがとうございます。 – skrzeczowas

答えて

7

私はあなたが何をしたいのかはっきりしていません。これはできますか?

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

また、できるだけ柔軟な入力パラメータを使用することをお勧めします。この方法にはList<T>の代わりにIEnumerable<T>を使用し、Repository<T>.Add()の方法でも使用してください。 lazy-evaluateクエリを渡すか、複数のLINQメソッドを連鎖させたい場合があります。

+0

+1まさに私が答えようとしていたものです。 – Sorax

+0

WOW。私は何をすべきかわからず、どこでも答えを見つけることができないときはいつでも、私はここに投稿するかもしれないと私は確かに答えを得るでしょう!依存関係の緩和に関するこれらの有用なヒントについて、ありがとうございました。私はあなたに私の新しい投稿を読むように依頼したいと思います - この質問の次の部分があります:)ありがとう、Paweł – skrzeczowas

3

Addメソッドを汎用にすることができます。

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

うん、これです:) – skrzeczowas

2

あなたはそれがタイプセーフ間接の1つの以上層で、あなたのオブジェクト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(); 
    } 
} 

は、だから今、あなたのDBクラスを変更することができます。

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

だからBookCollectionのインスタンスをAddメソッドに渡すことができ、これは100%型で安全な透過的な方法で動作します。

+0

これはまさにあなたが探している答えであるかどうかわかりませんが、キャストや型テストに大きく依存するよりも安全です。ジェネリック型のパラメータをオンにする必要がある場合は、何か問題があります。 – Juliet

+0

ジュリエット、あなたが言っていることは間違いなく正しいですが、実際に私は上記の質問をしました。私はどのように切り替えるべきかわからないからです。スイッチを使わないことを教えてくれればいいですね。 – skrzeczowas

2

他の人の回答に加えて、Inversion of Control(IoC)デザインパターンも参考にしてください。将来の仕事であなたの人生を単純化するかもしれません。

IoCが提供する依存性注入を使用すると、たとえば、EntitiesFactoryの使用を大幅に簡素化できます。

私は現時点でStructureMapを使用してIoCを実装していますが、それは私にとってはうまくいきます。

ここでは、IoCのMartin Fowler'sページとWikipedia'sページがあります。

+0

この回答ありがとうございます!私は非常に有益な情報がたくさんあることをとてもうれしく思います。 – skrzeczowas

1

あなたが返すものはEntitiesFactory()です。何を使用する必要があります。だから、問題は実際にあなたが示していないコードです。 EntitiesFactory()のコードを表示すると、達成しようとしていることについてより良いアイデアが得られます。

注:残念ながらリターンタイプをオーバーロードできないことを理解しています。

+0

残念ながら、上記のAddメソッドで書いたコードは、ある種の「擬似コード」です。私はこれが私が働きたいと思う方法であることを意味する:)以下の記事を読んでください。とにかくお返事ありがとうございます。 – skrzeczowas