Контекст активации "По запросу"... без запроса

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

Очистка после инициализации остается прежней.

Другие вопросы по тегам