リクエストごとに作成する必要のあるリポジトリがあります。これで、そのリポジトリを使用してデータを入力する必要があるシングルトンキャッシングオブジェクトがありますが、このオブジェクトはApplication_Startイベントで初期化されるため、リクエストコンテキストはありません。
Ninjectでこれを達成するための最良の方法はどれですか?
ありがとう。
リクエストごとに作成する必要のあるリポジトリがあります。これで、そのリポジトリを使用してデータを入力する必要があるシングルトンキャッシングオブジェクトがありますが、このオブジェクトはApplication_Startイベントで初期化されるため、リクエストコンテキストはありません。
Ninjectでこれを達成するための最良の方法はどれですか?
ありがとう。
アプリの起動時に現在HttpContext
が欠落しているため(IIS7統合モードの場合)、Ninjectは、アプリの起動への依存性を注入しようとInRequestScope
したときと同じように、バインドされたオブジェクトを確実に処理します。InTransientScope
Ninject(2.2)のソースコードでわかるように、次のようになります。
/// <summary>
/// Scope callbacks for standard scopes.
/// </summary>
public class StandardScopeCallbacks
{
/// <summary>
/// Gets the callback for transient scope.
/// </summary>
public static readonly Func<IContext, object> Transient = ctx => null;
#if !NO_WEB
/// <summary>
/// Gets the callback for request scope.
/// </summary>
public static readonly Func<IContext, object> Request = ctx => HttpContext.Current;
#endif
}
HttpContext.Current
はnull
アプリの起動時に発生するため、InRequestScope
バインドされたオブジェクトは、アプリの起動時にバインドされた場合と同じように扱われますInTransientScope
。
だからあなたはあなたの中に持つことができますglobal.asax
:
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<RequestScopeObject>().ToSelf().InRequestScope();
kernel.Bind<SingletonScopeObject>().ToSelf().InSingletonScope();
return kernel;
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
// init cache
this.Kernel.Get<SingletonScopeObject>().Init();
}
ただし、使用後にクリーンアップを実行する必要がありますRequestScopeObject
(たとえばDispose()
、が実装されている場合IDisposable
)。
public class SingletonScopeObject
{
private string cache;
private RequestScopeObject requestScopeObject;
public SingletonScopeObject(RequestScopeObject requestScopeObject)
{
this.requestScopeObject = requestScopeObject;
}
public void Init()
{
cache = this.requestScopeObject.GetData();
// do cleanup
this.requestScopeObject.Dispose();
this.requestScopeObject = null;
}
public string GetCache()
{
return cache;
}
}
別のアプローチ
RequestScopeObject
両方InRequestScope
をバインドし、InSingletonScope
次のように条件付きバインドを利用します。
kernel.Bind<SingletonScopeObject>()
.ToSelf()
.InSingletonScope()
.Named("singletonCache");
// as singleton for initialization
kernel.Bind<RequestScopeObject>()
.ToSelf()
.WhenParentNamed("singletonCache")
.InSingletonScope();
// per request scope binding
kernel.Bind<RequestScopeObject>()
.ToSelf()
.InRequestScope();
初期化後のクリーンアップは同じままです。