C# 如何使用castle windsor在限定范围的生活方式中注册服务,就像PerWebRequest一样?
我正在使用OWIN开发自托管web api,我需要使用Castle Windsor按范围注册服务 我知道使用HttpContext我可以通过PerWebRequest或HybridPerWebRequestPerThread实现这一点,但就我而言,我没有HttpContext 我已经创建了以下owin中间件,它将是在请求期间执行的第一个和最后一个中间件:C# 如何使用castle windsor在限定范围的生活方式中注册服务,就像PerWebRequest一样?,c#,owin,castle-windsor,owin-middleware,C#,Owin,Castle Windsor,Owin Middleware,我正在使用OWIN开发自托管web api,我需要使用Castle Windsor按范围注册服务 我知道使用HttpContext我可以通过PerWebRequest或HybridPerWebRequestPerThread实现这一点,但就我而言,我没有HttpContext 我已经创建了以下owin中间件,它将是在请求期间执行的第一个和最后一个中间件: public class SetupMiddleware : OwinMiddleware { public SetupMiddle
public class SetupMiddleware : OwinMiddleware
{
public SetupMiddleware(OwinMiddleware next) : base(next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
}
public override async Task Invoke(IOwinContext context)
{
IDisposable scope = null;
try
{
//here I am starting new scope
var container= IoCResolverFactory.GetContainer();
scope = container.BeginScope();
await Next.Invoke(context);
}
catch (Exception ex)
{
}
finally
{
//here I am disposing it
scope?.Dispose();
}
}
当我启动应用程序时,我在IoC容器中注册我的服务,如下所示:
container.BeginScope();
container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped());
container.BeginScope();
container.Register(Component.For().ImplementedBy().LifestyleScoped());
当我解析CurrentRequestService实例时,问题在于它不能按照owin中间件在新请求到来时启动它并在完成时处理它的作用域工作
您能告诉我如何在我的应用程序中注册每个作用域的服务,使其行为类似于PerWebRequest吗 可能有许多作用域 要使用由
SetupMiddleware
控制的范围,您需要在请求处理期间(例如在控制器操作中)解析ICurrentRequestService
比SetupMiddleware
更深的服务
因此,SetupMiddleware
将创建作用域,然后在控制器操作中ICurrentRequestService
将在该作用域内解析,最后SetupMiddleware
将通过调用scope.dispose()
来处理ICurrentRequestService
据我所知,目前您有以下情况:
// when application starts. Executes once
container.BeginScope(); // the 1st (application) scope beginning.
container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped());
var service = IoCResolverFactory.GetContainer().Resolve<ICurrentRequestService>();
//in SetupMiddleware. This code executes on every web request
var container = IoCResolverFactory.GetContainer();
scope = container.BeginScope(); // the request scope beginning
// here others middlewares
// here you can resolve ICurrentRequestService to use the request scope
scope?.Dispose(); // the request scope end
//应用程序启动时。执行一次
container.BeginScope();//第一个(应用)范围开始。
container.Register(Component.For().ImplementedBy().LifestyleScoped());
var service=IoCResolverFactory.GetContainer().Resolve();
//在安装中间件中。此代码在每个web请求上执行
var container=IoCResolverFactory.GetContainer();
scope=container.BeginScope();//请求范围正在开始
//这是其他的中间产品
//在这里,您可以解析ICurrentRequestService以使用请求范围
作用域?.Dispose();//请求范围结束
因此,
service
使用应用程序范围而不是请求范围 正如我所期望的,我应该定义一个自定义范围,以便在中间件中启动和处理
我已创建以下自定义作用域访问器:
public class OwinWebRequestScopeAccessor : IScopeAccessor
{
void IDisposable.Dispose() { }
ILifetimeScope IScopeAccessor.GetScope(CreationContext context)
{
IOwinContext owinContext = HttpContext.Current.GetOwinContext();
string key = SetupMiddleware.EnvironmentKey;
return owinContext.Environment[key] as ILifetimeScope;
}
}
然后,我对设置中间件进行了如下修改:
public class SetupMiddleware : OwinMiddleware
{
public const string EnvironmentKey = "WindsorOwinScope";
public SetupMiddleware(OwinMiddleware next) : base(next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
}
public override async Task Invoke(IOwinContext context)
{
ILifetimeScope lifetimeScope = new DefaultLifetimeScope();
try
{
context.Environment[EnvironmentKey] = lifetimeScope;
await Next.Invoke(context);
}
catch (Exception ex)
{
}
finally
{
context.Environment.Remove(EnvironmentKey);
lifetimeScope.Dispose();
}
}
}
然后,我使用上述范围注册了我的服务:
container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped<OwinWebRequestScopeAccessor>());
container.Register(Component.For().ImplementedBy().LifestyleScoped());
PS:
SetupMiddleware应该是owin管道中的第一个中间件
我希望我的代码能帮助其他人。除了
container.BeginScope()
在container.Register之前之外,一切看起来都是正确的(我看不出有任何必要在这里注册)。你能分享你的Startup
类和你解析服务的代码吗?那么我如何使用作用域的方式注册该服务?它将抛出作用域“作用域不可用。你忘了调用container.BeginScope()?”例外启动时我有一些需要解析该服务的代码。当我将我的服务注册为“container.register();”时,我使用以下代码“container.Resolve();”进行解析:container.register(Component.For().Instance(currentRequestService).LifestyleScoped();”它不处理它,当我将它注册为“container.register(Component.For().ImplementedBy().LifestyleScoped()”时我已经创建了一个示例。在这里,您可以在两个作用域中找到服务解析。我认为这不起作用。我仍然获得属性为null的CurrentRequestService实例(它们已在控制器中处理)。我认为我应该创建自定义作用域