简体   繁体   English

如何使用城堡温莎在诸如PerWebRequest之类的范围内的生活方式中注册服务?

[英]How to register services in scoped lifestyle behaving like PerWebRequest using castle windsor?

I am working on self-hosted web api using OWIN and I need to register a service per scope lifestyle using Castle Windsor. 我正在使用OWIN开发自托管的Web api,我需要使用Castle Windsor按范围的生活方式注册服务。

I know that using HttpContext I can achieve that using PerWebRequest or HybridPerWebRequestPerThread lifestyle but in my case I don't have HttpContext. 我知道使用HttpContext可以使用PerWebRequestHybridPerWebRequestPerThread的生活方式来实现,但就我而言,我没有HttpContext。

I have created the following owin middleware which will be the first and the last middleware will be executed during the request : 我创建了以下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();
        }
    }

And when I Startup my application I register my service inside the IoC container as following: 当我启动应用程序时,我在IoC容器中注册我的服务,如下所示:

container.BeginScope();
container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped());

The problem when I resolve instance of CurrentRequestService, it does not work as per scope which owin middleware will begin it when a new request comes and dispose it when it finishes. 当我解析CurrentRequestService实例时,该问题无法按范围工作,当新请求到来时,中间件将启动该中间件,并在完成时处置该中间件。

Could you please guide me to how can I register services per scope to behave like PerWebRequest in my application? 您能否指导我如何在每个范围内注册服务,使其在应用程序中表现得像PerWebRequest一样?

There may be many scopes. 可能有很多范围。

To use the scope that is controlled by SetupMiddleware you need to resolve ICurrentRequestService service somewhere deeper than SetupMiddleware during request processing (eg in controller action). 要使用由SetupMiddleware控制的范围,您需要在请求处理期间(例如,在控制器操作中)解决ICurrentRequestService服务, ICurrentRequestService服务比SetupMiddleware更深。

Thus, SetupMiddleware will create the scope, then in controller action ICurrentRequestService will be resolved inside that scope, finally SetupMiddleware will dispose ICurrentRequestService by calling scope.Dispose() . 因此, SetupMiddleware将创建范围,然后在控制器动作ICurrentRequestService解析到该范围内,最后SetupMiddleware将通过调用scope.Dispose()处置ICurrentRequestService

As I understand, currently you have something like this: 据我了解,目前您有以下类似信息:

// 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

Thus, service uses the application scope instead of the request scope. 因此, service使用应用程序范围而不是请求范围。

As I expected that I should define a custom scope to be started and dispose within a middleware . 正如我期望的那样,我应该定义一个自定义范围,以将其启动并放置在中间件中。

I have created the following custom scope accessor: 我创建了以下自定义作用域访问器:

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;
    }
}

Then I have modified my SetupMiddleware as followings: 然后,我对SetupMiddleware进行了如下修改:

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();
        }
    }
}

Then I registered my service using the above scope : 然后,我使用上述范围注册了服务:

container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped<OwinWebRequestScopeAccessor>());

PS: PS:

SetupMiddleware should be the first middleware in the owin pipeline. SetupMiddleware应该是owin管道中的第一个中间件。

I hope my code will help others. 希望我的代码对其他人有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在OWIN中使用Castle Windsor的PerWebRequest生活方式 - How to use Castle Windsor's PerWebRequest lifestyle with OWIN 温莎城堡FirstInterface()。Configure(c =&gt; c.LifeStyle.PerWebRequest) - Castle Windsor FirstInterface().Configure(c=> c.LifeStyle.PerWebRequest) 是否可以在Castle Windsor使用范围生活方式而不通过容器? - Is it possible to use a scoped lifestyle in Castle Windsor without passing the container around? WCF城堡温莎堡生活方式酒店? - Castle Windsor LifeStyle for WCF? 如何在温莎城堡注册mongodb? - How to register mongodb with castle windsor? 使用Castle-Windsor在MVC4中使用HttpClient的方式 - Lifestyle of a HttpClient in MVC4 using castle-windsor 如何使用ABP在我的所有临时依赖项中拥有PerWebRequest Lifestyle? - How to have a PerWebRequest Lifestyle in all my transient dependencies using ABP? 在Castle Windsor中向多个服务注册多个组件 - Register multiple components with multiple services in Castle Windsor 温莎城堡的生活方式无法按范围注册 - Castle Windsor scoped life style fails to register per scope 如何使用Castle Windsor的基本接口注册服务工厂模式 - How to register Service Factory Pattern using base interface with Castle Windsor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM