This commit is contained in:
Eugene Sadovoi 2019-05-22 19:42:09 -04:00
Родитель 6daa58a754
Коммит 2714dd330b
5 изменённых файлов: 152 добавлений и 47 удалений

Просмотреть файл

@ -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
}
*/
}