Как мне создать одноэлементную привязку с истекающим сроком действия?

#dependency-injection #ninject

#внедрение зависимостей #ninject

Вопрос:

Как я могу создать привязку для одноэлементного объекта с глобальной областью действия, срок действия экземпляра которого истекает через определенное время? После истечения срока действия объекта я бы хотел, чтобы Ninject обслуживал новый экземпляр до истечения срока действия этого экземпляра и т.д…

Псевдосвязывание, чтобы донести идею:

 Bind<Foo>().ToSelf()
    .InSingletonScope()
    .WithExpiration(someTimeSpan);
  

Я не ищу этот точный синтаксис, а скорее способ получить желаемый результат. По сути, это было бы похоже на использование Ninject в качестве скользящего кэша приложения.

Обновите методику, предложенную Яном, была правильной. Мне просто пришлось немного ее подправить, потому что использование DateTime в качестве контекстного ключа по какой-то причине не сработало. Вот что у меня получилось:

 var someTimeInFuture = DateTime.Now.AddSeconds(10); 
var fooScopeObject = new object();

Func<IContext, object> scopeCall = ctx =>
{
    if (someTimeInFuture < DateTime.Now)
    {
        someTimeInFuture = DateTime.Now.AddSeconds(10);
        fooScopeObject = new object();
    }

    return fooScopeObject;
};


Kernel.Bind<Foo>()
    .ToSelf()
    .InScope(scopeCall);   
  

Комментарии:

1. Обычно вы не хотите кэшировать службы, но данные, которыми управляют эти службы. Итак, почему вы на самом деле хотите это сделать?

2. Я полностью понимаю, о чем вы говорите. Это использовалось для получения дешевого кэширования в готовом приложении без внесения каких-либо серьезных архитектурных изменений… это означает, что мы специально использовали антишаблон, чтобы добиться некоторой производительности в паре проблемных мест без изменения архитектуры.

3. Спасибо за разъяснение. Это звучит как уважительная причина. В конечном итоге разработка (программного обеспечения) сводится к компромиссам.

4. что такое Kernel.Bind ?

Ответ №1:

По сути, вы определяете временную область. Вы можете выполнить привязку с помощью пользовательской функции области видимости и вернуть null через определенный промежуток времени.

 var someTimeInFuture = DateTime.Now.AddMinutes(5);
Func<IContext,object> scopeCall = ctx => DateTime.Now > someTimeInFuture ? null : someTimeInFuture;
Kernel.Bind<Foo>().ToSelf().InScope(scopeCall);
  

Я не могу протестировать это прямо сейчас, но это может сработать.

Комментарии:

1. Я думаю, вам понадобится функция<IContext, object> scopeCall = ctx => DateTime. Сейчас > Иногда в будущем? null: иногда в будущем;

2. Большое спасибо! Это было более или менее правильно, за исключением того, что вызов области видимости не сработал корректно при возврате DateTime. Структуры не должны работать для определения области видимости (мое лучшее предположение).

Ответ №2:

Вы можете использовать InScope (область функций). Как указано в документации:

Указывает, что экземпляры, активированные с помощью привязки, должны использоваться повторно до тех пор, пока объект, возвращаемый предоставленным обратным вызовом, остается активным (то есть не был собран мусор).

Вам нужно будет реализовать свою собственную пользовательскую область, которая обрабатывает ваш сценарий. Хорошим примером реализации вашей собственной области видимости является расширение именованной области из

https://github.com/ninject/ninject.extensions.namedscope