C# 如何使用castle windsor在限定范围的生活方式中注册服务,就像PerWebRequest一样?

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

我正在使用OWIN开发自托管web api,我需要使用Castle Windsor按范围注册服务

我知道使用HttpContext我可以通过PerWebRequestHybridPerWebRequestPerThread实现这一点,但就我而言,我没有HttpContext

我已经创建了以下owin中间件,它将是在请求期间执行的第一个和最后一个中间件:

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实例(它们已在控制器中处理)。我认为我应该创建自定义作用域