4

厳密に分離されたインターフェースを必要とするモジュールに取り組んでいます。具体的には、ルートオブジェクト(データソース)をインスタンス化した後、ユーザーはインターフェイスを介してオブジェクトモデルと対話することのみを想定しています。これらのインターフェイスを実装するインスタンスを提供するための実際のファクトリオブジェクト(プロバイダーと呼んでいます)がありますが、プロバイダーを取得するのが面倒です。そのために、データソースにいくつかのメソッドを提供しました。

public class MyDataSource
{
    private Dictionary<Type, Type> providerInterfaceMapping = new Dictionary<Type, Type>()
    {
        { typeof(IFooProvider), typeof(FooProvider) },
        { typeof(IBarProvider), typeof(BarProvider) },
        // And so forth
    };

    public TProviderInterface GetProvider<TProviderInterface>()
    {
        try
        {
            Type impl = providerInterfaceMapping[typeof(TProviderInterface)];
            var inst = Activator.CreateInstance(impl);

            return (TProviderInterface)inst;
        }
        catch(KeyNotFoundException ex)
        {
            throw new NotSupportedException("The requested interface could not be provided.", ex);
        }
    }
}

簡略化するために、その場でいくつかの詳細を変更しました(たとえば、このコードスニペットには、作成された実装インスタンスに渡されるパラメーターが含まれていません)。これは、C#でファクトリメソッドを実装するための優れた一般的なアプローチですか?

4

5 に答える 5

4

むしろ一歩下がって、ファクトリ メソッドを使用するのが良い考えかどうかを尋ねる必要があります。私の意見では、そうではありません。

ファクトリメソッドには複数の問題があり、あなたの例はいくつかを示しています:

  • 実装 (IFooProvider に加えて FooProvider) へのハード リファレンスが必要です。これはまさに最初に回避しようとしている状況です。コードの残りの部分が IFooProvider のみを使用する場合でも、ライブラリは引き続き FooProvider と密接に結合されています。他の開発者があなたのファクトリ メソッドを認識していない場合、直接 FooProvider を使用し始める可能性があります。
  • Activator.CreateInstance を使用しているため、デフォルトのコンストラクターを持つ実装のみをサポートします。これにより、ネストされた依存関係を使用できなくなります。

依存関係を手動で制御しようとする代わりに、依存性注入 (DI) を検討することをお勧めします。コードに IFooProvider が必要なときはいつでも、コンストラクター インジェクションを指定してください。

于 2009-10-26T15:19:04.783 に答える
3

依存性注入の独自の実装を再発明するのではなく、 Spring.NETMicrosoftUnityアプリケーションブロックなどの既存のライブラリを使用してください。

依存関係の挿入は、自分で解決する必要のない一般的なプログラミングの問題です。うまく機能する軽量のライブラリがいくつかあります(上記でいくつか言及しました)。それらは、依存関係を定義する宣言型モデルと命令型モデルの両方をサポートし、それらの機能に非常に優れています。

于 2009-10-26T15:41:54.943 に答える
1

技術的にはこれで問題ありませIProviderんが、ほとんどの場合、ファクトリを見ると通常同じ型のインターフェイスが返されます。FooProvider と BarProvider を使用する場合、なぜそれらに異なるインターフェースを使用するのでしょうか。私は1つのインターフェースを使用し、それを実装します。IFooProviderIBarProviderIProviderFooProviderBarProvider

于 2009-10-26T15:19:59.340 に答える
0

価値があるのは、このパターンを常に使用し、この種のロジックの一部を再利用可能なアセンブリに抽象化したことです。リフレクション、ジェネリック、および属性を使用して、実行時に具象型を見つけてバインドします。http://www.codeproject.com/KB/architecture/RuntimeTypeLoader.aspx

実装タイプはハードコードされておらず、さらに実装タイプはプロジェクト アセンブリ参照ではなく、インストールによって決定されるため、これは Mark の懸念に対処するのに役立ちます。

于 2009-10-26T15:53:18.867 に答える
0

ファクトリ メソッドを使用することの正誤に関係なく (それはあなたが尋ねたものではないためです!)、あなたの実装は私には問題ないように見えます。

型マッピングをハードコーディングするよりもうまくいく可能性があるのは、その情報を構成ファイルに入れてアプリにロードすることです。

于 2009-10-26T15:22:49.817 に答える