2

これは、基礎となるデータ ソースにアクセスする際に現在のユーザーになりすます必要があるデスクトップ アプリケーションです。

親オブジェクトのプロパティが null でなくなるまで依存関係をバインドしないように Ninject に指示するにはどうすればよいですか?

  1. アプリケーションは起動時にユーザー認証を強制します
  2. 認証されると、現在のユーザー資格証明への参照が、IMembershipService
  3. 基になるデータソースにアクセスするには、ユーザーを認証する必要があるため、commection 文字列が偽装する資格情報を示します。

私は実際にNHibernateを使用しており、認証時に提供されたユーザー資格情報に基づいて接続文字列を動的に作成する必要があります。

だから私は達成したいと思います:

public class DataModule : NinjectModule {
    public override void Load() {
        Bind<ISessionFactory>().ToProvider<SessionFactoryProvider>()
            .When( // IMembershipService.CurrentUser != null );
    } 
}

は にSessionProviderFactory依存するためIMembershipService.CurrentUser

これが世紀のデザインではないかもしれないことは承知していますが、出荷可能な製品を提供できるように、今のところこのように機能する必要があります. 後でリファクタリングできることを嬉しく思います。

セッションファクトリープロバイダー

public class SessionFactoryProvider : Provider<ISessionFactory> {
    public class SessionFactoryProvider(IMembershipService service) {
        membershipService = service;
    }

    protected override ISessionFactory CreateInstance(IContext context) {
        Configuration nhconfig = new Configuration().Configure();
        nhconfig.AddAssembly(Assembly.GetExecutingAssembly());
        nhconfig.Properties["connection.connection_string"] = buildConnectiongString();
        return nhconfig.BuildSessionFactory();
    }

    private string buildConnectionString() {
        return string.Format(membershipService.GetDefaultConnectionString()
            , membershipService.CurrentUser.DatabaseInstanceName
            , membershipService.CurrentUser.Login
            , membershipService.CurrentUser.Password);
    }

    private readonly IMembershipService membershipService;
}

セッションプロバイダー

public class SessionProvider : Provider<ISession> {
    public class SessionProvider(ISessionFactory factory) {
        sessionFactory = factory;
    }

    protected override ISession CreateInstance(IContext context) {
        return sessionFactory.OpenSession();
    }

    private readonly ISessionFactory sessionFactory;
}

IMembershipService.CurrentUser実際のところ、アプリケーションの起動時に をインスタンス化することはできません。ユーザーは最初にシステムに対して認証する必要があるため、ActivationException.

ISession のアクティブ化中にエラーが発生しました

一致するバインディングは利用できず、タイプは自己バインディング可能ではありません。

アクティベーション パス:

3) InquiriesRepository 型のコンストラクターのパラメーター セッションへの依存関係 ISession の注入

2) InquiriesManagementPresenter タイプのコンストラクターのパラメーター リポジトリへの依存関係 IInquiriesRepository の注入

1) お問い合わせのお願い管理プレゼンター

提案:

1) ISession のバインディングを定義したことを確認します。

2) バインディングがモジュールで定義されている場合は、モジュールがカーネルにロードされていることを確認します。

3) 誤って複数のカーネルを作成していないことを確認してください。

4) コンストラクター引数を使用している場合は、パラメーター名がコンストラクターのパラメーター名と一致していることを確認してください。

5) モジュールの自動ロードを使用している場合は、検索パスとフィルターが正しいことを確認してください。

では、どうすれば作れますか?

デザインの改善提案は大歓迎です。しかし、うまく機能するためにはそれが必要であることを覚えておいてください。次の配信のためにリファクタリングします。

編集

おそらくコンテキスト/スコープ依存性注入を使用できるようです。

How to use the additional Ninject Scopes of NamedScope

それでも、私のシナリオでここで機能させる方法がわかりません。

アップデート

読んでみると、おそらく条件付きバインディングよりもコンテキスト バインディングの方が私のニーズに適しているのではないかと疑い始めています。

何かご意見は?

条件付きバインディングに関連する各記事は、条件付き状態バインディングではなく、条件付きタイプ バインディングについて述べています。

私のシナリオでは、それが条件付きの状態バインディングであると具体的に信じているため、コンテキストバインディングについての考えです。

次に、2 つのバインディングがあります。

  1. ユーザー認証前
  2. ユーザー認証後

ISessionFactoryしたがって、アプリケーションの起動時にのインスタンスが必要ないため、おそらく遅延注入を使用する必要があります。これにより、問題が解決します。

私はここで少し損をしています...

4

1 に答える 1

3

条件付きバインディングを作成できる場合があります。

IBindingRoot.Bind<IFoo>().To<Foo>()
    .When(request => request.ParentContext.Kernel.Get<IUserService>().AuthenticatedUser != null);

でもオススメしません(-_-;)

@パケイン

When 条件は、IFoo を要求するたびに実行されます。これは別のリクエストに変換されるため、多少コストがかかります。

また、このアプローチは、親リクエストがある場合にのみ機能します。a を実行するIResolutionRoot.Get<IFoo>()と、 がスローされNullReferenceExceptionます。

構文によって提供されるカーネルにアクセスすることで、これを回避できます。しかし、ninjectの将来のリリースでそこにとどまるかどうかはわかりません...


また、「完全に初期化」(=> 認証) された後にオブジェクト ツリーの特定の部分のみをインスタンス化することを保証するアプリケーション ブートストラップ メカニズムを持つことは、より優れた設計です。少なくとも私の意見では。

于 2014-04-03T15:32:09.637 に答える