使用ServiceStack我一直坚持自托管Web应用程序中对象生存期管理的问题。
我的要求:
一般问题:
Castle Windsor IoC实现了自己的每个请求生命周期策略,但它绑定到http模块,因此它仅适用于IIS托管应用程序。因此,我必须实现我的自定义IScopeAccessor(由Castle Windsor提供)来处理对象的生命周期。这里的问题是没有钩子,我可以用它来绑定当前的请求。
给出
public class MyScopeAccessor : IScopeAccessor
{
public ILifetimeScope GetScope(CreationContext context)
{
//implement it
}
}
我必须实现GetScope方法。
我无法完成两个主要想法:
使用[Threadstatic]
在MyScopeAccessor中我只存储
[ThreadStatic]
private static ILifetimeScope _currentLifetimeScope;
并在第一个GetScope之后创建新范围,如果它尚未初始化。
问题:
使用IRequest实例
在MyScopeAccessor中我只存储
private static readonly ConcurrentDictionary<IRequest, ILifetimeScope> LifetimeScopes;
并在相应的自定义ServiceRunner方法(OnBeforeEachRequest,OnAfterEachRequest)中创建和处置当前生命周期范围。
问题:
此外,有趣的是,如果ServiceStack默认Funq IoC解决了这个问题。
答案 0 :(得分:3)
Funq会处理RequestScoped dependencies,它会在RequestContext.Instance.Items[]
字典中存储请求上下文依赖项。
任何可以在RequestContext.Instance.TrackDisposable()
注册的一次性用品都会在请求结束时自动处理。
在每个请求结束时AppHost.OnEndRequest()
被触发,该请求将通过并释放存储在RequestContext中的该请求的所有依赖项。
如果您的Windsor ContainerAdapter实现IRelease
接口,则会自动调用它以释放任何可以自行处理的实例。如果您想更改默认行为,这两个API都可以在AppHost
中覆盖:
public virtual void OnEndRequest()
{
var disposables = RequestContext.Instance.Items.Values;
foreach (var item in disposables)
{
Release(item);
}
RequestContext.Instance.EndRequest();
}
public virtual void Release(object instance)
{
try
{
var iocAdapterReleases = Container.Adapter as IRelease;
if (iocAdapterReleases != null)
{
iocAdapterReleases.Release(instance);
}
else
{
var disposable = instance as IDisposable;
if (disposable != null)
disposable.Dispose();
}
}
catch { /*ignore*/ }
}