Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to "BeginScope" for a specific Custom Scoped lifestyle in Castle Windsor?

I've created a custom Scope Accessor (it simply returns the DefaultLifetimeScope) to be able to add a custom scoped lifestyle. The component is then registered as

Component
   .For<..>
   .LifestyleScoped<CustomScope>()

However, I am at a loss as how to actually start a new CustomScope scope/lifetime. The documentation shows starting a new scope using

using (Container.BeginScope()) {
   // ..
}

but my goal is to create/begin/start a specific scope, not that for a generic LifestyleScoped() registration. The new scope should only affect components explicitly registered to CustomScope; not generic scoped components or components registered against other scoped lifestyles.

What is the process to begin a (My Custom Scope) scope / lifetime?

Please link to the relevant documentation; as I'm asking because I was not able to find it readily. The code is using Castle Windsor 3.3.


Background:

I am coming from Autofac and am looking for the equivalent of an Instance Per Matching Lifetime Scope to establish a UoW over an EF context. There may be multiple UoWs "per request" and there might be different UoWs for different repositories - I would also like the support for nesting in the future.

While there are numerous articles talking about creating a UoW pattern, they are [all] tied (incorrectly, IMOHO) to some context such as HTTP or WFC request - and that is not what this question is about. I am specifically interested in how to start a custom scope that flows down through the call graph and "lives inside" the using block.


Notes:

The BoundTo() (and LifestyleBoundTo()/LifestyleBoundToNearest()) lifestyles work against the object-graph (and requires altering the types) and switching to such is not strictly a solution/answer to this question. However, if a good case can be made for them ..

like image 846
user2864740 Avatar asked Nov 01 '22 12:11

user2864740


1 Answers

Container.BeginScope() initializes a new CallContextLifeTimeScope.

https://github.com/castleproject/Windsor/blob/aa9b8b353ee2e533d586495eec254e216f800c09/src/Castle.Windsor/MicroKernel/Lifestyle/LifestyleExtensions.cs

using Scope = Castle.MicroKernel.Lifestyle.Scoped.CallContextLifetimeScope;

public static class LifestyleExtensions
{
    public static IDisposable BeginScope(this IKernel kernel)
    {
        return new Scope(kernel);
    }
    /* rest of the code removed for simplicity */
}

This extension method doesn't care about your custom ILifetimeScope implementation.

Instead of calling Container.BeginScope(), you can just new CustomScope() and dispose it in the end to make sure your "custom scoped objects" released properly.

You can call Container.BeginScope() inside your CustomScope and dispose them both in the end in order to support components registered with default lifetime scope.

like image 89
Cankut Avatar answered Nov 09 '22 10:11

Cankut