1

最終的に Ninject が DI を処理する方法をある程度理解しましたが、次の問題に直面しました。

2 つの WCF ServiceHost オブジェクトをコンストラクター パラメーターとして受け取るクラスがあるとします。

public ActivitySinkServer(IDataProvider dataProvider, ServiceHost posClients, ServiceHost activitySinkOperatorClients)

最初は ServiceHost の依存関係が 1 つしかなかったので、次のようにバインディングを簡単に処理できました。

public class CommunicationModule: NinjectModule
{
public override void Load()
        {
            Bind<POSClient>().ToSelf().WithConstructorArgument("posManager", Kernel.Get<POSManager>());

            this.Bind<ServiceHost>().ToMethod(ctx => ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("singletonInstance", c => c.Kernel.Get<POSClient>())));
        }
}

このシナリオでは、シングルトン オブジェクトで初期化された依存関係をActivitySinkServer解決できます。ServiceHostNinjectServiceHost

2 つの ServiceHost 依存関係があるので、Ninject に、どのコンストラクター パラメーターでどれをフィードするかをどのように伝えることができますか? (マニュアルの Ninject 属性やその他のものを使用できたことはわかっています)。

アップデート:

私は先に進み、ちょうど使用しました

.When(request => request.Target.Name == "posClients");
.When(request => request.Target.Name == "activitySinkOperatorClients");

ターゲット コンストラクターの変数名を明示的に指定します。それに害はありません。ただし、誰かがよりエレガントでオブジェクト指向のアプローチを持っている場合は、喜んで答えてください。

4

1 に答える 1

0

あなたのやり方は100%問題ありません。より「エレガントな」方法は、名前付きバインディングまたはメタデータを使用することです。

ちなみに、この場合はコンストラクターを使用しない方がはるかに良いです。そのように初期化すると、WCF は他のインスタンス化モード ( など) を使用できなくなるためです。Ninject と WCF でインスタンス化を処理し、代わりに型ベースのコンストラクターを使用します。singletonInstanceServiceHostPerCall

名前付きバインディングの例は次のとおりです。

class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<ServiceHost>().To<NinjectServiceHost>().Named("POS")
            .WithConstructorArgument("serviceType", typeof(PosService))
            .WithConstructorArgument("baseAddresses", new Uri[0]);

        Bind<ServiceHost>().To<NinjectServiceHost>().Named("ActivitySink")
            .WithConstructorArgument("serviceType", typeof(ActivitySink))
            .WithConstructorArgument("baseAddresses", new Uri[0]);
    }
}

public class Server
{
    private readonly ServiceHost posHost;
    private readonly ServiceHost activitySink;

    public Server(IDataProvider dataProvider,
        [Named("POS")] posHost,
        [Named("ActivitySink")] activitySink)
    {
        this.posHost = posHost;
        this.activitySink = activitySink;
    }
}

baseAddressesNinject が正しいオーバーロードを選択するには、コンストラクタ引数を初期化する必要があることに注意してください。具体的に初期化すると、ベースアドレスを検索new Uri[0]するデフォルトの動作が発生するだけなapp.configので、空の配列を渡すことについて心配する必要はありません。

これによりServerクラスが Ninject 自体に結合されますが、通常、ServiceHostインスタンスはライブラリではなくアプリケーション バイナリで作成されるため、結合は問題になりません。

Whenリファクタリング中に壊れる可能性が低いため、構文に対するこのアプローチを好みます。誰かがいつの日かコンストラクターのパラメーター名を変更することを決定する可能性は低くありません。また、それらの名前に依存していることを視覚的に示すものはまったくなく、Visual Studio の自動リファクタリングでその依存関係を検出する方法もありません。

したがって、IMO、ここでは属性を使用して依存関係を明示することをお勧めします。そうすれば、誰かが後で3 番目のサービス ホストを追加することを決定した場合、属性を追加して対応する Ninject モジュールを更新する必要があることがすぐにわかります。

于 2011-08-14T20:48:08.660 に答える