8

Ninjectフレームワークを使用してMVC3アプリを構築しています。初期化に時間がかかるサービスがあり、最後にこのサービスにはユーザー固有の情報を含むオブジェクトが含まれるため、ユーザーセッションがアクティブである限り、そのサービスを再利用する必要があります。そのサービスを何度も初期化することを避けることができます

だから私の質問は

Ninjectを使用してサービスをバインドする場合、どの種類のスコープを選択する必要がありますか?Ninjectにはスコープごとのセッションがないので、要件を実装するための最良の方法は何ですか?または私はまったく間違った方向に行きましたか?

現在のController.User.Identity.Nameから取得したユーザー名の詳細に基づいてサービスを作成するサービスの1つにカスタムプロバイダーを作成しました。userNameローカル変数がないため、以下のコードは機能しません。IContextから取得できるように、Ninjectを介してユーザー名の値をカスタムプロバイダーに渡すにはどうすればよいですか?

public class TfsConnectionManagerProvider : Provider<TfsConnectionManager>
    {
        protected override TfsConnectionManager CreateInstance(IContext context)
        {
            Uri serverUri = new Uri(ConfigurationHelper.TfsServerUrl);
            // Connect to the server without impersonation
            using (TfsTeamProjectCollection baseUserConnection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(serverUri))
            {
                // Get the identity management service
                IIdentityManagementService ims = baseUserConnection.GetService<IIdentityManagementService>();

                // Get the identity to impersonate
                TeamFoundationIdentity identity = ims.ReadIdentity
                (
                    IdentitySearchFactor.AccountName,
                    userName,  //NOTE: How can I get user name value from IContext???
                    MembershipQuery.None,
                    ReadIdentityOptions.None
                );

                // Connect using the impersonated identity
                using (TfsTeamProjectCollection impersonatedConnection = new TfsTeamProjectCollection(serverUri, identity.Descriptor))
                {
                    WorkItemStore store = impersonatedConnection.GetService<WorkItemStore>();

                    return new TfsConnectionManager
                    {
                        Store = store
                    };
                }
            }
        }
    }
4

3 に答える 3

7

Ninjectでは、セッションスコープは意図的に提供されていません。これは、ほとんどすべての状況でサービスをセッション状態にすることが間違っているためです。セッション状態は多くの欠点をもたらすため、セッション状態の使用には十分注意する必要があります。

そもそもステートレスアプリケーションを用意してみてください。

セッションスコープにデータを含める正当な理由がある場合は、そのデータ(サービスではない)をセッション状態にし、処理(データと機能の分離)にシングルトン、一時、または要求スコープのサービスを使用します。

于 2012-05-04T11:04:40.103 に答える
2

インスタンスの作成にカスタムプロバイダーを使用することがわかり、カスタムプロバイダーで、インスタンスがセッションに存在するかどうかを確認しました。

バインディングは次のように行われます。

Bind<IRepository>().ToProvider(new TfsRepositoryProvider());

カスタムプロバイダーは以下のとおりです

public class TfsRepositoryProvider : Provider<TfsRepository>
    {
        private const string SesTfsRepository = "SES_TFS_REPOSITORY";

        protected override TfsRepository CreateInstance(IContext context)
        {
            // Retrieve services from kernel
            HttpContextBase httpContext = context.Kernel.Get<HttpContextBase>();

            if (httpContext == null || httpContext.Session == null)
            {
                throw new Exception("No bind service found in Kernel for HttpContextBase");
            }

            return (httpContext.Session[SesTfsRepository] ?? (
                    httpContext.Session[SesTfsRepository] = new TfsRepository(context.Kernel.Get<IWorkItemStoreWrapper>()))
                ) as TfsRepository;
        }
    }
于 2012-05-09T15:44:12.930 に答える
0

さて、ユーザー情報をアプリケーションにキャッシュ/保存し、(最近の)ユーザー情報がない場合にのみ外部サービスを呼び出すことができます。ユーザー情報検索の「レイヤー」では、これら2つの可能性をプログラムするだけです。

キャッシュする場所は、完全にあなた次第です。この情報は、たとえばローカルデータベースに保存できます。

どうやら私はあなたが間違っていることを理解しました、私の謝罪(私の元の答えの下)。

たとえば、サービスの静的メンバーを保持する(抽象)ファクトリを使用して、再利用できるようにすることができます。

サービスによっては、これには望ましくない副作用が発生する可能性があります(Data Servicesでこれを1回実行し、ASP.NET MVC3アプリケーションでは、何らかの魔法が発生したため、データコンテキストが少し混乱しました)。これで言いたいのは、注意してよくテストすることだけです。

于 2012-05-04T08:24:54.780 に答える