11using System ;
2- using System . Threading ;
3- using Unity . Exceptions ;
42using Unity . Lifetime ;
53
6- namespace Unity . Microsoft . DependencyInjection
4+ namespace Unity . Microsoft . DependencyInjection . Lifetime
75{
8- public class InjectionSingletonLifetimeManager : LifetimeManager , IRequiresRecovery
6+ public class InjectionSingletonLifetimeManager : ContainerControlledLifetimeManager
97 {
108 #region Fields
119
12- protected object _value ;
1310 private ILifetimeContainer _lifetime ;
14- private readonly object _lockObj = new object ( ) ;
15-
11+
1612 #endregion
1713
1814
@@ -22,100 +18,36 @@ public InjectionSingletonLifetimeManager(ILifetimeContainer lifetime)
2218 }
2319
2420
25- /// <summary>
26- /// Retrieve a value from the backing store associated with this Lifetime policy.
27- /// </summary>
28- /// <returns>the object desired, or null if no such object is currently stored.</returns>
29- /// <remarks>Calls to this method acquire a lock which is released only if a non-null value
30- /// has been set for the lifetime manager.</remarks>
31- public override object GetValue ( ILifetimeContainer container = null )
21+ protected override void SynchronizedSetValue ( object newValue , ILifetimeContainer container = null )
3222 {
33- Monitor . Enter ( _lockObj ) ;
34- var result = SynchronizedGetValue ( container ) ;
35- if ( result != null )
36- {
37- Monitor . Exit ( _lockObj ) ;
38- }
39- return result ;
23+ base . SynchronizedSetValue ( newValue , container ) ;
24+ _lifetime . Add ( new DisposableAction ( ( ) => RemoveValue ( _lifetime ) ) ) ;
4025 }
4126
42- /// <summary>
43- /// Performs the actual retrieval of a value from the backing store associated
44- /// with this Lifetime policy.
45- /// </summary>
46- /// <returns>the object desired, or null if no such object is currently stored.</returns>
47- /// <remarks>This method is invoked by <see cref="SynchronizedLifetimeManager.GetValue"/>
48- /// after it has acquired its lock.</remarks>
49- protected virtual object SynchronizedGetValue ( ILifetimeContainer container )
27+ protected override LifetimeManager OnCreateLifetimeManager ( )
5028 {
51- return _value ;
29+ return new InjectionSingletonLifetimeManager ( _lifetime ) ;
5230 }
5331
5432
55- /// <summary>
56- /// Stores the given value into backing store for retrieval later.
57- /// </summary>
58- /// <param name="newValue">The object being stored.</param>
59- /// <param name="container">The container this value belongs to.</param>
60- /// <remarks>Setting a value will attempt to release the lock acquired by
61- /// <see cref="SynchronizedLifetimeManager.GetValue"/>.</remarks>
62- public override void SetValue ( object newValue , ILifetimeContainer container = null )
63- {
64- SynchronizedSetValue ( newValue , container ) ;
65- TryExit ( ) ;
66- }
67-
68- /// <summary>
69- /// Performs the actual storage of the given value into backing store for retrieval later.
70- /// </summary>
71- /// <param name="newValue">The object being stored.</param>
72- /// <param name="container"></param>
73- /// <remarks>This method is invoked by <see cref="SynchronizedLifetimeManager.SetValue"/>
74- /// before releasing its lock.</remarks>
75- protected virtual void SynchronizedSetValue ( object newValue , ILifetimeContainer container )
76- {
77- _value = newValue ;
78- if ( _value is IDisposable disposable ) _lifetime . Add ( disposable ) ;
79- }
33+ #region Nested Types
8034
81- /// <summary>
82- /// A method that does whatever is needed to clean up
83- /// as part of cleaning up after an exception.
84- /// </summary>
85- /// <remarks>
86- /// Don't do anything that could throw in this method,
87- /// it will cause later recover operations to get skipped
88- /// and play real havoc with the stack trace.
89- /// </remarks>
90- public void Recover ( )
35+ private class DisposableAction : IDisposable
9136 {
92- TryExit ( ) ;
93- }
37+ private readonly Action _action ;
9438
95- protected virtual void TryExit ( )
96- {
97- #if ! NET40
98- // Prevent first chance exception when abandoning a lock that has not been entered
99- if ( ! Monitor . IsEntered ( _lockObj ) ) return ;
100- #endif
101- try
39+ public DisposableAction ( Action action )
10240 {
103- Monitor . Exit ( _lockObj ) ;
41+ _action = action ?? throw new ArgumentNullException ( nameof ( action ) ) ;
10442 }
105- catch ( SynchronizationLockException )
43+
44+ public void Dispose ( )
10645 {
107- // Noop here - we don't hold the lock and that's ok.
46+ _action ( ) ;
10847 }
10948 }
11049
111- public override void RemoveValue ( ILifetimeContainer container = null )
112- {
113- TryExit ( ) ;
114- }
50+ #endregion
11551
116- protected override LifetimeManager OnCreateLifetimeManager ( )
117- {
118- return new InjectionSingletonLifetimeManager ( _lifetime ) ;
119- }
12052 }
12153}
0 commit comments