2

OK Dependency Ninja's、ここにあなたのための1つがあります...

カーネルから要求しているタイプに基づいて、Ninject が依存関係を構築する方法を変更したいと考えています。

次のコンストラクタを持つ DbConnectionFactory クラスがあります。

    public DbConnectionFactory()
        : this(MyDatabase.ConnectionString)
    {
    }

    public DbConnectionFactory(string connectionString)
        : this(DbProviderFactories.GetFactory("System.Data.SqlClient"), connectionString)
    {
    }

「デフォルト」バインディングの場合、Ninject にパラメーターなしのコンストラクターを使用してもらいます。

        this.Bind<IDbConnectionFactory>().To<DbConnectionFactory>();

コード内の特定のクラスでは、connectionString パラメータを提供するために Ninject が必要です。私は次のようにバインディングをセットアップしようとしました:

        this.Bind<IDbConnectionFactory>().To<DbConnectionFactory>().Only(
            When.Context.InstanceOf(typeof(IRepository))).WithArgument(
            "connectionString", MyOtherDatabase.ConnectionString);

ただし、Ninject でデフォルトのコンストラクターを使用することしかできません。

明らかな何かが欠けているに違いありません!

4

2 に答える 2

3

ここには少しレイヤーが多すぎるように聞こえます。DatabaseGateway が必要な理由 接続を直接管理するために、ADO.NET プロバイダー ファクトリを使用して接続を作成しないのはなぜですか (Ninject を介して接続することもできます)。それとも、リポジトリ パターンで NHibernate のようなものを使用し、これを使用してオブジェクトをマップしますか?

とにかく、常に長いコンストラクターを使用し、状況に応じて MyDatabase.ConnectionString または MyOtherDatabase.ConnectionString を交互に渡すのはどうですか? ここここで説明されているようにプロバイダーを使用できますが、どうしても必要な場合を除き、それらを避けるようにしています。

  1. 2 つの新しい属性を定義する

    public class DefaultDatabaseAttribute : Attribute {}
    public class OtherDatabaseAttribute : Attribute {}
    
  2. コンストラクターで適切な属性を使用して DatabaseGateway 引数を装飾します。

    public class OneRepository : IRepository
    {
        public OneRepository([DefaultDatabase]DatabaseGateway factory)
        {
        }
    }
    
    public class TwoRepository : IRepository
    {
        public TwoRepository([OtherDatabase]DatabaseGateway factory)
        {
        }
    }
    

    プロバイダーは次のようになります。

    public class DatabaseGatewayProvider : SimpleProvider<DatabaseGateway>
    {
            protected override DatabaseGateway CreateInstance(Ninject.Core.Activation.IContext context)
            {
                IDbConnectionFactory factory;
                if (context.Member.IsDefined(typeof(DefaultDatabaseAttribute), false))
                {
                    factory = context.Kernel.get<IDbConnectionFactory>(With.Parameters.ConstructorArgument("connectionString", MyDatabase.ConnectionString)));
                }
                else if (context.Member.IsDefined(typeof(OtherDatabaseAttribute), false))
                {
                    factory = context.Kernel.get<IDbConnectionFactory>(With.Parameters.ConstructorArgument("connectionString", MyOtherDatabase.ConnectionString)));
                }
    
                return new DatabaseGateway(factory);
            }
    }
    

このモデルを拡張して属性を追加し、ファクトリを DatabaseGateway で返す必要があるかどうかを判断できます。

扱いにくいですが、関係するレイヤーの数を考えると、これが最善の方法かもしれません。

于 2009-07-21T13:12:15.077 に答える
1

この記事もあなたを助けるかもしれません。ジェフが言ったように、With.Parameters.ConstructorArgument()を使用することをお勧めします。ConstructorArgumentのチェーンを継続するか、Dictionaryを使用して、複数の引数を渡すことができます。お役に立てれば!

于 2009-09-14T07:38:29.987 に答える