This project is read-only.

ExecutionContextScopeLifestyle and Windows Service

Oct 26, 2014 at 9:11 PM
All,

I'm having a complete mental break down here on the proper usage of the ExecutionContextScopeLifestyle. I have a windows service application
            var container = new Container();
            //class level variable so I can dispose when app ends
            _globalScope = new Scope();

            // Register an initializer that stores instances for disposal, and gets hooked to Singleton 
            // registrations who's implementation type implements IDisposable.
            //https://simpleinjector.codeplex.com/discussions/568508
            container.RegisterInitializer(
                data => _globalScope.RegisterForDisposal((IDisposable)data.Instance),
                context => context.Producer.Lifestyle == Lifestyle.Singleton &&
                    typeof(IDisposable).IsAssignableFrom(context.Registration.ImplementationType));

            container.RegisterSingle(() => new DocumentStore
            {
                Url = "http://localhost:8080",
                DefaultDatabase = "mydatabase",
            }.Initialize());

            container.Register(() =>
            {
                var session = container.GetInstance<IDocumentStore>()
                    .OpenSession();
                return session;
            }, new ExecutionContextScopeLifestyle(true));

            container.Register(() =>
            {
                var session = container.GetInstance<IDocumentStore>()
                    .OpenAsyncSession();
                return session;
            }, new ExecutionContextScopeLifestyle(true));
Notice that I'm using a "new" ExecutionContextScopeLifestyle for both the ISession and IAsyncSession. That doesn't seem right to me. Should I be using a single instance of ExecutionContextScopeLifestyle for both registrations? Also, for this to actually work, don't I have to use
using (container.BeginExecutionContextScope()) {
Oct 26, 2014 at 9:29 PM
Edited Oct 28, 2014 at 8:09 PM
All (built-in) Lifestyle types are thread-safe and are safe for reuse. But functionally, there is no difference between creating new instances on the fly and reusing the same instance all over the place. You can find more information about it in this Stackoverflow q/a. That q/a also describes why it is better to reuse the same lifestyle instance.
Oct 26, 2014 at 9:50 PM
ok that's great it feels a bit better to me to use the variable over, but what about
container.BeginExecutionContextScope()
Do I need to use this to actually make the magic work? Since the container doesn't ever dispose anything (https://simpleinjector.codeplex.com/discussions/568508). Will everything dispose (including this ExecutionScope) when I dispose the global Scope I created at the beginning?
Oct 27, 2014 at 8:33 AM
Which magic are you referring to? You need to wrap the beginning and disposal of an execution context scope around the request you are processing. So you begin a scope, resolve from the container, invoke a method on the resolved object and dispose the scope. When you call dispose at the end of the request (what ever a 'request' means in your application), all scoped objects that are created during the lifetime of that scope will get disposed.

To be clear, you don't need to start an application wide execution context scope. The global scope you are creating has no relationship with the execution context scope. When you call BeginExecutionContextScope(), this method creates its own Scope instance and stores it in the CallContext. Your global scope and the scope(s) in the CallContext will have no relationship, and will not be able to 'see' each other.

But do note that this global scope that you created will only dispose instances that are registered to it. Since you call RegisterInitializer and hook that to disposable singletons, only disposable singletons that are created throughout the lifetime of the application will get disposed when you call globalScope.Dispose(). Nothing else. No execution context scopes will be disposed at that point. But those execution context scopes should already have been disposed, since you should dispose each scope at the end of a request.
Marked as answer by dot_NET_Junkie on 11/3/2014 at 1:23 AM
Oct 28, 2014 at 8:06 PM
The magic that is SimpleInjector of course. I apologize for... well pretty much everything in this post. I should have turned off the computer long before I asked these questions. I understand now what I'm supposed to do. Thanks as always for your timely and comprehensive answers.