Контекст активации "По запросу"... без запроса
У меня есть хранилище, которое необходимо создать для каждого запроса. Теперь существует одноэлементный объект кэширования, который должен использовать этот репозиторий для заполнения себя данными, но этот объект инициализируется в событии Application_Start, поэтому контекст запроса отсутствует.
Какой лучший способ добиться этого с Ninject?
Благодарю.
1 ответ
Как ток 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();
Очистка после инициализации остается прежней.