/src/LinFu.IoC/Scope.cs
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}