Experimenting with lifetime
This commit is contained in:
Родитель
6daa58a754
Коммит
2714dd330b
|
@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
|
|||
using System.Security;
|
||||
using System.Text.RegularExpressions;
|
||||
using Unity.Exceptions;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
|
@ -33,7 +34,7 @@ namespace Unity.Builder
|
|||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
public string? Name => Registration?.Name;
|
||||
|
||||
public object? Resolve(Type type, string? name)
|
||||
{
|
||||
|
@ -131,27 +132,27 @@ namespace Unity.Builder
|
|||
#endif
|
||||
public ResolvePlanDelegate DependencyResolvePipeline => ContainerContext.Container.DependencyResolvePipeline;
|
||||
|
||||
public PipelineDelegate Pipeline
|
||||
public ResolveDelegate<BuilderContext> Pipeline
|
||||
{
|
||||
get
|
||||
{
|
||||
if (null != Registration?.PipelineDelegate) return Registration.PipelineDelegate;
|
||||
if (null != Registration?.Pipeline) return Registration.Pipeline;
|
||||
|
||||
Debug.Assert(null != Registration);
|
||||
|
||||
lock (Registration)
|
||||
{
|
||||
// Double check
|
||||
if (null != Registration.PipelineDelegate) return Registration.PipelineDelegate;
|
||||
if (null != Registration.Pipeline) return Registration.Pipeline;
|
||||
|
||||
// Create a pipeline
|
||||
var context = this;
|
||||
PipelineBuilder builder = new PipelineBuilder(ref context);
|
||||
Registration.PipelineDelegate = builder.PipelineDelegate() ??
|
||||
Registration.Pipeline = builder.Pipeline() ??
|
||||
throw new InvalidOperationException($"Failed to create pipeline for registration: {Registration}");
|
||||
}
|
||||
|
||||
return Registration.PipelineDelegate;
|
||||
return Registration.Pipeline;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +211,35 @@ namespace Unity.Builder
|
|||
#endif
|
||||
};
|
||||
|
||||
return context.Pipeline(ref context).Result;
|
||||
var manager = registration.LifetimeManager switch
|
||||
{
|
||||
null => TransientLifetimeManager.Instance,
|
||||
PerResolveLifetimeManager _ => (LifetimeManager?)context.Get(typeof(LifetimeManager)) ??
|
||||
TransientLifetimeManager.Instance,
|
||||
_ => registration.LifetimeManager
|
||||
};
|
||||
|
||||
// Check if already got value
|
||||
var value = manager.GetValue(ContainerContext.Lifetime);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
if (registration.LifetimeManager is SynchronizedLifetimeManager synchronized)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = context.Pipeline(ref context);
|
||||
}
|
||||
catch
|
||||
{
|
||||
synchronized.Recover();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
value = context.Pipeline(ref context);
|
||||
|
||||
manager.SetValue(value, ContainerContext.Lifetime);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ namespace Unity
|
|||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
Name = name,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace Unity
|
|||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
Name = name,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
|
@ -49,7 +48,6 @@ namespace Unity
|
|||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
Name = name,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using Unity.Builder;
|
||||
|
@ -11,6 +12,7 @@ using Unity.Injection;
|
|||
using Unity.Lifetime;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
|
@ -205,30 +207,65 @@ namespace Unity
|
|||
[SecuritySafeCritical]
|
||||
object? IUnityContainer.Resolve(Type type, string? name, params ResolverOverride[] overrides)
|
||||
{
|
||||
var registration = GetRegistration(type ?? throw new ArgumentNullException(nameof(type)), name);
|
||||
|
||||
// Check if already got value
|
||||
var value = null != registration.LifetimeManager
|
||||
? registration.LifetimeManager.GetValue(LifetimeContainer)
|
||||
: LifetimeManager.NoValue;
|
||||
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
var synchronized = registration.LifetimeManager as SynchronizedLifetimeManager;
|
||||
|
||||
// Setup Context
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
Type = type,
|
||||
Overrides = overrides,
|
||||
Registration = GetRegistration(type ?? throw new ArgumentNullException(nameof(type)), name),
|
||||
Registration = registration,
|
||||
ContainerContext = Context,
|
||||
};
|
||||
|
||||
// Create an object
|
||||
try
|
||||
// Execute pipeline
|
||||
if (null == synchronized)
|
||||
{
|
||||
// Execute pipeline
|
||||
var task = context.Pipeline(ref context);
|
||||
Debug.Assert(task.IsCompleted);
|
||||
return task.Result;
|
||||
try
|
||||
{
|
||||
value = context.Pipeline(ref context);
|
||||
registration.LifetimeManager?.SetValue(value, LifetimeContainer);
|
||||
return value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is InvalidRegistrationException ||
|
||||
ex is CircularDependencyException ||
|
||||
ex is ObjectDisposedException)
|
||||
{
|
||||
var message = CreateMessage(ex);
|
||||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is InvalidRegistrationException ||
|
||||
ex is CircularDependencyException ||
|
||||
ex is ObjectDisposedException)
|
||||
else
|
||||
{
|
||||
var message = CreateMessage(ex);
|
||||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
try
|
||||
{
|
||||
value = context.Pipeline(ref context);
|
||||
registration.LifetimeManager?.SetValue(value, LifetimeContainer);
|
||||
return value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
synchronized.Recover();
|
||||
if (ex is InvalidRegistrationException ||
|
||||
ex is CircularDependencyException ||
|
||||
ex is ObjectDisposedException)
|
||||
{
|
||||
var message = CreateMessage(ex);
|
||||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
}
|
||||
else throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +282,7 @@ namespace Unity
|
|||
var context = new BuilderContext
|
||||
{
|
||||
Existing = existing ?? throw new ArgumentNullException(nameof(existing)),
|
||||
|
||||
List = new PolicyList(),
|
||||
Type = ValidateType(type, existing.GetType()),
|
||||
Overrides = overrides,
|
||||
Registration = GetRegistration(type ?? throw new ArgumentNullException(nameof(type)), name),
|
||||
|
@ -256,9 +293,7 @@ namespace Unity
|
|||
try
|
||||
{
|
||||
// Execute pipeline
|
||||
var task = context.Pipeline(ref context);
|
||||
Debug.Assert(task.IsCompleted);
|
||||
return task.Result;
|
||||
return context.Pipeline(ref context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is InvalidRegistrationException || ex is CircularDependencyException || ex is ObjectDisposedException)
|
||||
|
|
|
@ -12,6 +12,7 @@ using Unity.Injection;
|
|||
using Unity.Lifetime;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
|
@ -189,6 +190,68 @@ namespace Unity
|
|||
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
ValueTask<object?> IUnityContainerAsync.ResolveAsync(Type type, string? name, params ResolverOverride[] overrides)
|
||||
{
|
||||
var registration = GetRegistration(type ?? throw new ArgumentNullException(nameof(type)), name);
|
||||
|
||||
// Check if already got value
|
||||
var value = null != registration.LifetimeManager
|
||||
? registration.LifetimeManager.GetValue(LifetimeContainer)
|
||||
: LifetimeManager.NoValue;
|
||||
|
||||
// TODO: Need to change sync mechanism
|
||||
|
||||
if (LifetimeManager.NoValue != value) return new ValueTask<object?>(value);
|
||||
|
||||
return new ValueTask<object?>(Task.Factory.StartNew<object?>(delegate
|
||||
{
|
||||
// Setup Context
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
Type = type,
|
||||
Overrides = overrides,
|
||||
Registration = registration,
|
||||
ContainerContext = Context,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
try
|
||||
{
|
||||
return context.Pipeline(ref context);
|
||||
}
|
||||
catch (Exception ex)
|
||||
when (ex is InvalidRegistrationException ||
|
||||
ex is CircularDependencyException ||
|
||||
ex is ObjectDisposedException)
|
||||
{
|
||||
var message = CreateMessage(ex);
|
||||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public ValueTask<IEnumerable<object>> Resolve(Type type, Regex regex, params ResolverOverride[] overrides)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Child container management
|
||||
|
||||
/// <inheritdoc />
|
||||
IUnityContainerAsync IUnityContainerAsync.CreateChildContainer() => CreateChildContainer();
|
||||
|
||||
/// <inheritdoc />
|
||||
IUnityContainerAsync? IUnityContainerAsync.Parent => _parent;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
// Backups
|
||||
/*
|
||||
ValueTask<object?> IUnityContainerAsync.ResolveAsync(Type type, string? name, params ResolverOverride[] overrides)
|
||||
{
|
||||
// Setup Context
|
||||
|
@ -217,24 +280,5 @@ namespace Unity
|
|||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ValueTask<IEnumerable<object>> Resolve(Type type, Regex regex, params ResolverOverride[] overrides)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Child container management
|
||||
|
||||
/// <inheritdoc />
|
||||
IUnityContainerAsync IUnityContainerAsync.CreateChildContainer() => CreateChildContainer();
|
||||
|
||||
/// <inheritdoc />
|
||||
IUnityContainerAsync? IUnityContainerAsync.Parent => _parent;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче