我目前正在使用AutoFac作为ServiceStack Web服务应用的DI容器。我能够配置接线和所有内容,但在阅读了Scopes部分之后,我很遗憾在注册我的组件时最好使用哪个范围。在我们的特定情况下,我认为PerHttpRequest范围可以正常(如果我错了请纠正我)我希望在请求结束后立即处理依赖关系。
我的问题是,如何在容器中设置它?我似乎无法在autofac中包含的方法中找到“PerHttpRequest”生命周期范围。我也不确定ServiceStack是否会在幕后为我做这种自动化。
我在.Net 4上的ServiceStack 3.9.35上使用Autofac 3.0.1(作为常规ASP主机运行,而不是MVC)。我也使用了here描述的类作为IContainer适配器。
答案 0 :(得分:5)
我想避免依赖MVC的开销,所以第一个答案对我来说并不适用。
相反,我使用Funq来注册PerRequest ILifetimeScope,并在解析依赖关系之前解析ConatinerAdaptor中的ILifetimeScope。
public class AutofacLifetimeScopeIocAdapter : IContainerAdapter
{
private readonly Container _requestContainer;
public AutofacLifetimeScopeIocAdapter(Funq.Container requestContainer)
{
_requestContainer = requestContainer;
}
public T Resolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
return currentContainer.Resolve<T>();
}
public T TryResolve<T>()
{
var currentContainer = _requestContainer.Resolve<ILifetimeScope>();
T result;
if (currentContainer.TryResolve<T>(out result))
{
return result;
}
return default(T);
}
}
然后用这个
初始化_autofacContainerRoot = builder.Build();
IContainerAdapter adapter = new AutofacLifetimeScopeIocAdapter(container);
container.Register<ILifetimeScope>((c) => _autofacContainerRoot.BeginLifetimeScope())
.ReusedWithin(ReuseScope.Request);
container.Adapter = adapter;
然后用
进行清理public override void OnEndRequest()
{
var currentContainer = _container.Resolve<ILifetimeScope>();
currentContainer.Dispose();
base.OnEndRequest();
}
这似乎与Autofac - SingleInstance,InstancePerDependency和现在的InstancePerLifetimeScope(perRequest)一样。
HostContext.Instance.Items集合上的Mythz响应很可能用于删除
的需要var currentContainer = _container.Resolve<ILifetimeScope>();
分辨率,这应该可以提高性能。
答案 1 :(得分:4)
我想我已经弄清楚如何使这项工作(使用Autofac 2.6,我现在卡住了。)它涉及使用以下适配器和Autofac.Mvc3包:
public class AutofacIocAdapter : IContainerAdapter
{
private readonly IContainer _autofacRootContainer;
private readonly Container _funqContainer;
public AutofacIocAdapter(IContainer autofacRootContainer, Container funqContainer)
{
// Register a RequestLifetimeScopeProvider (from Autofac.Integration.Mvc) with Funq
var lifetimeScopeProvider = new RequestLifetimeScopeProvider(autofacRootContainer,null);
funqContainer.Register<ILifetimeScopeProvider>(x => lifetimeScopeProvider);
// Store the autofac application (root) container, and the funq container for later use
_autofacRootContainer = autofacRootContainer;
_funqContainer = funqContainer;
}
public T Resolve<T>()
{
return ActiveScope.Resolve<T>();
}
public T TryResolve<T>()
{
T result;
if (ActiveScope.TryResolve(out result))
{
return result;
}
return default(T);
}
private ILifetimeScope ActiveScope
{
get
{
// If there is an active HttpContext, retrieve the lifetime scope by resolving
// the ILifetimeScopeProvider from Funq. Otherwise, use the application (root) container.
return HttpContext.Current == null
? _autofacRootContainer
: _funqContainer.Resolve<ILifetimeScopeProvider>().GetLifetimeScope();
}
}
}
实施步骤:
答案 2 :(得分:2)
注意RequestScope in ServiceStack's IOC仅指ServiceStack的内置Funq IOC。
要在另一个IOC容器(如AutoFac)中使用RequestScope,通常需要在请求结束时通知AutoFac,以便它可以清理其所有请求范围的实例。为此,ServiceStack提供了AppHostBase.OnEndRequest()
挂钩,您可以覆盖它以在每个请求结束时获取执行自定义逻辑。
我不熟悉AutoFac的自定义生命周期范围如何运作,但有关它的更多详细信息,请参阅:
在ServiceStack中管理实例可能有用的其他信息是,放入HostContext.Instance.Items
字典中的每个实例或添加到HostContext.Instance.TrackDisposable
的一次性实例都是automatically disposed at the end of each request。
答案 3 :(得分:2)
更新2015-11-25 :我使用全局请求和响应过滤器更改了实施。我将ServiceStack V3和V4解决方案都放入了这个repository,两个版本都以nuget packages的形式提供。
我通过在Application_BeginRequest中打开一个新范围并在Application_EndRequest中处理来解决了这个问题。在容器适配器中,我检查这个范围是否存在并使用它,如果没有,我使用容器。这允许使用.InstancePerRequest()注册范围。
用gists here描述。