PageRenderTime 102ms CodeModel.GetById 40ms app.highlight 4ms RepoModel.GetById 56ms app.codeStats 1ms

/src/LinFu.IoC/Scope.cs

http://github.com/philiplaureano/LinFu
C# | 97 lines | 55 code | 18 blank | 24 comment | 13 complexity | 6dc6a01397ca2c146e68d3b203dd2267 MD5 | raw file
 1using System;
 2using System.Collections.Generic;
 3using System.Threading;
 4using LinFu.IoC.Configuration;
 5using LinFu.IoC.Interfaces;
 6
 7namespace LinFu.IoC
 8{
 9    /// <summary>
10    ///     Represents a class that keeps track of all the disposable objects
11    ///     created within a service container and disposes them when
12    ///     the scope itself has been disposed.
13    /// </summary>
14    public class Scope : IScope, IPostProcessor, IInitialize
15    {
16        private readonly List<WeakReference> _disposables = new List<WeakReference>();
17        private IServiceContainer _container;
18        private bool _disposed;
19        private int _threadId;
20
21
22        /// <summary>
23        ///     Inserts the scope into the target <paramref name="source">container</paramref>.
24        /// </summary>
25        /// <param name="source">The container that will hold the scope instance.</param>
26        public void Initialize(IServiceContainer source)
27        {
28            lock (this)
29            {
30                _container = source;
31
32                // Use the same thread ID as the service instantiation call
33                _threadId = Thread.CurrentThread.ManagedThreadId;
34
35                // Monitor the container for 
36                // any IDisposable instances that need to be disposed
37                _container.PostProcessors.Add(this);
38            }
39        }
40
41
42        /// <summary>
43        ///     Monitors the <see cref="IServiceContainer" /> for any services that are created and automatically disposes them
44        ///     once the <see cref="IScope" /> is disposed.
45        /// </summary>
46        /// <param name="result">The <see cref="IServiceRequestResult" /> that describes the service being instantiated.</param>
47        public void PostProcess(IServiceRequestResult result)
48        {
49            if (_disposed)
50                return;
51
52            // Only handle requests from the same thread
53            if (_threadId != Thread.CurrentThread.ManagedThreadId)
54                return;
55
56            // Ignore any nondisposable instances
57            if (result.ActualResult == null || !(result.ActualResult is IDisposable))
58                return;
59
60            var disposable = result.ActualResult as IDisposable;
61            var weakRef = new WeakReference(disposable);
62            _disposables.Add(weakRef);
63        }
64
65
66        /// <summary>
67        ///     Disposes the services that have been created while the scope has been active.
68        /// </summary>
69        public void Dispose()
70        {
71            if (_disposed)
72                return;
73
74            if (_threadId != Thread.CurrentThread.ManagedThreadId)
75                throw new InvalidOperationException(
76                    "The scope object can only be disposed from within the thread that created it.");
77
78            // Dispose all child objects
79            foreach (var item in _disposables)
80            {
81                if (item == null)
82                    continue;
83
84                var target = item.Target as IDisposable;
85                if (target == null)
86                    continue;
87
88                target.Dispose();
89            }
90
91            _disposed = true;
92
93            // Remove the scope from the target container
94            _container.PostProcessors.Remove(this);
95        }
96    }
97}