Skip to content

Commit 8586e7b

Browse files
committed
Async support for Lifetime
1 parent adea547 commit 8586e7b

File tree

5 files changed

+77
-60
lines changed

5 files changed

+77
-60
lines changed

src/Extensions/Container/UnityContainerAsync.cs

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -806,24 +806,11 @@ public static IUnityContainerAsync RegisterFactory(this IUnityContainerAsync con
806806
public static T ResolveAsync<T>(this IUnityContainerAsync container, params ResolverOverride[] overrides)
807807
{
808808
var unity = container ?? throw new ArgumentNullException(nameof(container));
809-
var value = unity.ResolveAsync(typeof(T), null, overrides);
809+
var task = unity.ResolveAsync(typeof(T), null, overrides);
810810

811-
if (value.IsCompleted) return (T) value.Result;
812-
813-
try
814-
{
815-
var task = value.AsTask();
816-
task.Wait();
817-
818-
return (T) task.Result;
819-
}
820-
catch (AggregateException ex)
821-
{
822-
if (1 == ex.InnerExceptions.Count)
823-
throw ex.InnerException;
824-
825-
throw;
826-
}
811+
return task.IsCompleted
812+
? (T)task.Result
813+
: (T)task.GetAwaiter().GetResult();
827814
}
828815

829816
/// <summary>
@@ -839,24 +826,11 @@ public static T ResolveAsync<T>(this IUnityContainerAsync container, params Reso
839826
public static T ResolveAsync<T>(this IUnityContainerAsync container, string name, params ResolverOverride[] overrides)
840827
{
841828
var unity = container ?? throw new ArgumentNullException(nameof(container));
842-
var value = unity.ResolveAsync(typeof(T), name, overrides);
843-
844-
if (value.IsCompleted) return (T)value.Result;
845-
846-
try
847-
{
848-
var task = value.AsTask();
849-
task.Wait();
850-
851-
return (T)task.Result;
852-
}
853-
catch (AggregateException ex)
854-
{
855-
if (1 == ex.InnerExceptions.Count)
856-
throw ex.InnerException;
829+
var task = unity.ResolveAsync(typeof(T), name, overrides);
857830

858-
throw;
859-
}
831+
return task.IsCompleted
832+
? (T)task.Result
833+
: (T)task.GetAwaiter().GetResult();
860834
}
861835

862836
/// <summary>

src/Lifetime/Abstracts/LifetimeManager.cs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ namespace Unity.Lifetime
88
/// </summary>
99
public abstract class LifetimeManager
1010
{
11-
protected object SyncRoot { get; } = new object();
12-
1311
/// <summary>
1412
/// This value represents Invalid Value. Lifetime manager must return this
1513
/// unless value is set with a valid object. Null is a value and is not equal
@@ -28,8 +26,42 @@ public abstract class LifetimeManager
2826
/// <value>True is this instance already in use, False otherwise.</value>
2927
public virtual bool InUse { get; set; }
3028

29+
30+
#region Constructors
31+
32+
public LifetimeManager()
33+
{
34+
Set = SetValue;
35+
Get = GetValue;
36+
TryGet = TryGetValue;
37+
}
38+
39+
#endregion
40+
3141

32-
#region LifetimeManager Members
42+
#region Optimizers
43+
44+
public virtual Func<ILifetimeContainer, object> TryGet { get; protected set; }
45+
46+
public virtual Func<ILifetimeContainer, object> Get { get; protected set; }
47+
48+
public virtual Action<object, ILifetimeContainer> Set { get; protected set; }
49+
50+
#endregion
51+
52+
53+
#region LifetimeManager Members
54+
55+
/// <summary>
56+
/// Retrieves a value from the backing store associated with this Lifetime policy.
57+
/// </summary>
58+
/// <remarks>
59+
/// This method does not block and does not acquire a lock on synchronization
60+
/// primitives.
61+
/// </remarks>
62+
/// <param name="container">The container this lifetime is associated with</param>
63+
/// <returns>the object desired, or null if no such object is currently stored.</returns>
64+
public virtual object TryGetValue(ILifetimeContainer container = null) => GetValue(container);
3365

3466
/// <summary>
3567
/// Retrieves a value from the backing store associated with this Lifetime policy.

src/Lifetime/Abstracts/SynchronizedLifetimeManager.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ public abstract class SynchronizedLifetimeManager : LifetimeManager, IDisposable
3535

3636
#endregion
3737

38+
/// <inheritdoc/>
39+
public override object TryGetValue(ILifetimeContainer container = null)
40+
{
41+
if (Monitor.TryEnter(_lock))
42+
{
43+
var result = SynchronizedGetValue(container);
44+
Monitor.Exit(_lock);
45+
return result;
46+
}
47+
else
48+
return NoValue;
49+
}
50+
51+
3852
/// <inheritdoc/>
3953
public override object GetValue(ILifetimeContainer container = null)
4054
{

src/Lifetime/Managers/ContainerControlledLifetimeManager.cs

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,16 @@ public class ContainerControlledLifetimeManager : SynchronizedLifetimeManager,
3333
/// <value>This field holds a strong reference to the associated object.</value>
3434
protected object Value = NoValue;
3535

36-
private Func<ILifetimeContainer, object> _currentGetValue;
37-
private Action<object, ILifetimeContainer> _currentSetValue;
38-
3936
#endregion
4037

4138

4239
#region Constructor
4340

4441
public ContainerControlledLifetimeManager()
4542
{
46-
_currentGetValue = base.GetValue;
47-
_currentSetValue = base.SetValue;
43+
Set = base.SetValue;
44+
Get = base.GetValue;
45+
TryGet = base.TryGetValue;
4846
}
4947

5048
#endregion
@@ -55,34 +53,26 @@ public ContainerControlledLifetimeManager()
5553
/// <inheritdoc/>
5654
public override object GetValue(ILifetimeContainer container = null)
5755
{
58-
return _currentGetValue(container);
56+
return Get(container);
5957
}
6058

6159
/// <inheritdoc/>
6260
public override void SetValue(object newValue, ILifetimeContainer container = null)
6361
{
64-
_currentSetValue(newValue, container);
65-
_currentSetValue = (o, c) => throw new InvalidOperationException("InjectionParameterValue of ContainerControlledLifetimeManager can only be set once");
66-
_currentGetValue = SynchronizedGetValue;
62+
Set(newValue, container);
63+
Set = (o, c) => throw new InvalidOperationException("ContainerControlledLifetimeManager can only be set once");
64+
Get = SynchronizedGetValue;
65+
TryGet = SynchronizedGetValue;
6766
}
6867

6968
/// <inheritdoc/>
70-
protected override object SynchronizedGetValue(ILifetimeContainer container = null)
71-
{
72-
return Value;
73-
}
69+
protected override object SynchronizedGetValue(ILifetimeContainer container = null) => Value;
7470

7571
/// <inheritdoc/>
76-
protected override void SynchronizedSetValue(object newValue, ILifetimeContainer container = null)
77-
{
78-
Value = newValue;
79-
}
72+
protected override void SynchronizedSetValue(object newValue, ILifetimeContainer container = null) => Value = newValue;
8073

8174
/// <inheritdoc/>
82-
public override void RemoveValue(ILifetimeContainer container = null)
83-
{
84-
Dispose();
85-
}
75+
public override void RemoveValue(ILifetimeContainer container = null) => Dispose();
8676

8777
#endregion
8878

src/Lifetime/Managers/ExternallyControlledLifetimeManager.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class ExternallyControlledLifetimeManager : LifetimeManager,
1313
{
1414
#region Fields
1515

16-
private WeakReference _value = new WeakReference(NoValue);
16+
private WeakReference _value;
1717

1818
#endregion
1919

@@ -27,7 +27,14 @@ public class ExternallyControlledLifetimeManager : LifetimeManager,
2727
/// <returns>the object desired, or null if no such object is currently stored.</returns>
2828
public override object GetValue(ILifetimeContainer container = null)
2929
{
30-
return _value.Target;
30+
if (null == _value) return NoValue;
31+
32+
var target = _value.Target;
33+
if (_value.IsAlive) return target;
34+
35+
_value = null;
36+
37+
return NoValue;
3138
}
3239

3340
/// <summary>

0 commit comments

Comments
 (0)