Как мне управлять временем жизни пользовательского IResourceProvider?
Я использовал этот подход для добавления собственного поставщика ресурсов в мое приложение ASP.NET MVC, но у меня возникли некоторые проблемы с управлением временем жизни объекта.
Я использую Castle Windsor, поэтому у меня есть следующая реализация фабрики:
public class DefaultResourceProviderFactory : ResourceProviderFactory
{
public override IResourceProvider CreateGlobalResourceProvider(string classKey)
{
// IoC is a static helper class that gives me static access to the
// container. IoC.Resolve<T>(args...) simply calls container.Resolve<T>(args...).
return IoC.Resolve<IResourceProvider>(new { resourceType = "Global" });
}
public override IResourceProvider CreateLocalResourceProvider(string virtualPath)
{
// resourceType
return IoC.Resolve<IResourceProvider>(new { ResourceType = virtualPath });
}
}
Тем не менее IResourceProvider
Кажется, я зарегистрировался в контейнере, и его время жизни не было правильно настроено. У него есть некоторые другие собственные зависимости, некоторые из которых имеют несколько сложный образ жизни (на веб-запрос или на транзакцию), поэтому я зарегистрировал IResourceProvider
как переходный, чтобы гарантировать, что его зависимости всегда действительны. Но структура MVC наступает на мои пальцы, сохраняя ссылку на IResourceProvider
через веб-запросы, что вызывает ObjectDisposedExceptions
когда его зависимости были признаны недействительными при следующем запросе.
Что я хотел бы сделать, так это заставить MVC-фреймворк использовать фабрику каждый раз, когда ему нужен экземпляр моего IResourceProvider
и - если возможно - также вызывать IoC.Release(provider)
или что-то подобное, когда это сделано с этим.
Как мне микро-управлять образом жизни обычая IResourceProvider
таким образом, что фреймворк MVC будет уважать?
1 ответ
После поиска вокруг различных способов контролировать время жизни IResourceProvider
Сам я решил, что лучше было бы реорганизовать мою реализацию, чтобы использовать Средство Typed Factory.
мой IResourceProvider
Реализация ранее выглядела примерно так:
public class CachedResourceProvider : IResourceProvider {
CachedResourceProvider(IResourceRecordRepository repo) { /* ... */ }
// other members...
}
Теперь я изменил это вместо этого:
public class CachedResourceProvider : IResourceProvider {
CachedResourceProvider(IResourceRecordRepositoryFactory repo) { /* ... */ }
// other members...
}
Заводской интерфейс является новым, определяемым как
public interface IResourceRecordRepositoryFactory {
IResourceRecord NewInstance();
void Release(IResourceRecord instance);
}
и каждое использование частного _repo
экземпляр в CachedResourceProvider
был подвергнут рефакторингу до трех операторов: получить экземпляр репо с фабрики, использовать экземпляр репо для извлечения / сохранения чего-либо, выпустить экземпляр через фабрику.
Я зарегистрировал их так:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IResourceRecordRepositoryFactory>().AsFactory());
Теперь, несмотря на то, что MVC хранит ссылку на моего провайдера ресурсов через веб-запросы, используемые им сервисы повторно выбираются из контейнера Windsor при каждом их использовании, поэтому контейнер полностью контролирует их время жизни.