10

私は MVC3 Web サイトに取り組んでおり、Ninject を使用して依存関係を解決しようとしています。次のシナリオがあります。

public class UserModelBinder : IModelBinder
{
    //[Inject]
    public UserDataService userData { get; set; }

    public object BindModel(
        ControllerContext controllerContext,
        ModelBindingContext bindingContext)
    {
        Guid UserID =
            (Guid)Membership.GetUser().ProviderUserKey;

        //userDataService = DependencyResolver.Current
        //    .GetService<UserDataService>();

        User user = userDataService.GetUser(UserID);

        return user;
    }
}

コードのコメント行に気づきましたか?

バインダーを次のように登録しGlobal.asaxます

ModelBinders.Binders[typeof(User)] = new UserModelBinder();

だから、私は実際に建設を通して注入することはできません.

UserDataService依存関係のチェーンがあります: UserDataService -> UserRepository -> Context. そこでNinjectを使うと良いでしょう。

[Inject]問題は、上記の宣言のコメントを外しuserDataて、Ninject にオブジェクトをパラメーターとして挿入させようとすると、何らかの理由で機能しないことです。null 参照例外が発生します。

(インターフェイスがなく、オブジェクトをそれ自体にバインドしている可能性があります: ??UserDataServicekernel.Bind<UserDataService>().ToSelf(); )

コードに別のコメント行があります。

userDataService = DependencyResolver.Current
    .GetService<UserDataService>();

これがコメント解除されると、セットアップが機能し、正しいオブジェクトが挿入されますが、現在は DependencyResolver に依存しており、それは言うよりもはるかに優れているわけではありませんuserDataService = new UserDataService()

何か不足していますか?オブジェクトをパラメーターとして注入し、Ninject または DependencyResolver への依存関係を導入しない別の方法はありますか?

4

3 に答える 3

7

モデル バインダーは、データ変換のみを行う必要があり、サービスに依存してはならず、データベース通信をトリガーしてはなりません。これは、アプリケーションの別の部分で行う必要があります。Action メソッドは を受け取るだけで、コントローラー内 (または、ビジネス コマンド内などの下位層) からGuid userId呼び出す必要があります。これを行うことにより、問題は存在しなくなります。userDataService.GetUser(UserID);

于 2012-06-01T13:02:21.667 に答える
5

あなたはこれを行うことができます:

public class UserModelBinder : IModelBinder
{
    public Func<UserDataService> UserData { get; set; }

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Guid UserID = (Guid)Membership.GetUser().ProviderUserKey;

        User u = UserData().GetUser(UserID);

        return u;
    }
}

次に、配線すると:

ModelBinders.Binders[typeof(User)] = new UserModelBinder() 
{  
    userData = () => DependencyResolver.Current.GetService<UserDataService>();
}

利点はUserModelBinder、コンテナが使用されていることを認識していないことですが、まだ注入のために開いています。

しかし、私はスティーブンに同意します-これにモデルバインダーを使用することはまったく正しくないようです. 代わりICurrentUserContextに、コントローラーに を挿入すると、実装によって現在のユーザーが返されます。その後、コントローラー アクションにパラメーターを追加する必要さえありません。

于 2012-06-01T14:16:30.413 に答える
1

を使用しDependencyResolver.Currentてサービスを受けてください。これは、実際には を使用するよりもはるかに優れています。これnewは、そのサービスを取得することをサービスのタイプに関連付けていないことを意味するためです。UserDataService後でクライアント コードを変更せずに、抽象化を行い、さまざまなバリアントをプラグインすることを決定できます。これが重要なポイントです。

また、DependencyResolver.Currentは settableIDependencyResolverであるため、そのフレームワークが気に入った場合は、Ninject でサポートするクラスを使用して、そのインターフェイスを自分で実装できます。

MVC3 で依存性注入を行う別の方法は、独自の をセットアップするIControllerActivatorことです。これにより、必要に応じて代わりにコンストラクター注入を行うことができます。

于 2012-06-01T12:11:33.093 に答える