Restore point
This commit is contained in:
Родитель
25528874c6
Коммит
eb6e5ef941
|
@ -1,148 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private BuildPipelineAsync DefaultLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var registration = Registration;
|
||||
var synchronized = manager as SynchronizedLifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// In Sync mode just execute pipeline
|
||||
if (!context.RunAsync)
|
||||
{
|
||||
var value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// Compose down the chain
|
||||
value = pipeline(ref c);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
catch (Exception ex)// when (null != synchronized)
|
||||
{
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
synchronized?.Recover();
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
}
|
||||
|
||||
// Async mode
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew<object?>(() =>
|
||||
{
|
||||
var value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
try
|
||||
{
|
||||
value = pipeline(ref c);
|
||||
manager.SetValue(value, lifetime);
|
||||
return value;
|
||||
}
|
||||
catch when (null != synchronized)
|
||||
{
|
||||
synchronized.Recover();
|
||||
throw;
|
||||
}
|
||||
});
|
||||
return new ValueTask<object?>(task);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private PipelineDelegate DefaultLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var registration = Registration;
|
||||
var synchronized = manager as SynchronizedLifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
|
||||
var value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
try
|
||||
{
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
catch (Exception ex)// when (null != synchronized)
|
||||
{
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
synchronized?.Recover();
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private BuildPipelineAsync PerResolveLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
object value;
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// In Sync mode just execute pipeline
|
||||
if (!context.RunAsync)
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
};
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref c);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
// Async mode
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew<object?>(() =>
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
return pipeline(ref c);
|
||||
});
|
||||
|
||||
return new ValueTask<object?>(task);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private PipelineDelegate PerResolveLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
object value;
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
|
||||
// Get it from context
|
||||
var manager = (LifetimeManager?)context.Get(typeof(LifetimeManager));
|
||||
|
||||
// Return if holds value
|
||||
if (null != manager)
|
||||
{
|
||||
value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
{
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
return new ValueTask<object?>(value);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Exceptions;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private BuildPipelineAsync PerThreadLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
// Verify is not async
|
||||
if (context.RunAsync || context.RunningAsync)
|
||||
{
|
||||
var ex = new InvalidRegistrationException("Lifetime:PerThread is not designed to participate in async operations");
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
// Compose
|
||||
try
|
||||
{
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var value = manager.GetValue(lifetime);
|
||||
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
Parent = IntPtr.Zero,
|
||||
};
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref c);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
catch (Exception ex)// when (null != synchronized)
|
||||
{
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private PipelineDelegate PerThreadLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
// Verify is not async
|
||||
if (context.IsAsync)
|
||||
{
|
||||
var ex = new InvalidRegistrationException("Lifetime:PerThread is not designed to participate in async operations");
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
// Compose
|
||||
try
|
||||
{
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var value = manager.GetValue(lifetime);
|
||||
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
catch (Exception ex)// when (null != synchronized)
|
||||
{
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private BuildPipelineAsync TransientLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
// Async mode
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
//In Sync mode just execute pipeline
|
||||
if (!context.RunAsync)
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
Parent = IntPtr.Zero,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
var value = pipeline(ref c);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew<object?>(() =>
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
Parent = IntPtr.Zero,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
return pipeline(ref c);
|
||||
});
|
||||
|
||||
return new ValueTask<object?>(task);
|
||||
};
|
||||
}
|
||||
|
||||
private PipelineDelegate TransientLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
var value = pipeline(ref context);
|
||||
return new ValueTask<object?>(value);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,9 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using System.Security;
|
||||
using Unity.Builder;
|
||||
using Unity.Injection;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using static Unity.UnityContainer;
|
||||
|
@ -32,33 +34,48 @@ namespace Unity
|
|||
{
|
||||
Type = registration.Type ?? typeof(object);
|
||||
Name = registration.Name;
|
||||
BuildType = registration.BuildType;
|
||||
BuildRequired = registration.BuildRequired;
|
||||
LifetimeManager = registration.LifetimeManager;
|
||||
InjectionMembers = registration.InjectionMembers;
|
||||
|
||||
Registration = registration;
|
||||
ContainerContext = container.Context;
|
||||
|
||||
Seed = Registration.Pipeline;
|
||||
Seed = registration.Pipeline;
|
||||
_enumerator = pipelines.GetEnumerator();
|
||||
Debug.Assert(null != _enumerator);
|
||||
}
|
||||
|
||||
public PipelineBuilder(Type type, string? name, UnityContainer container, IEnumerable<Pipeline> pipelines)
|
||||
{
|
||||
Seed = null;
|
||||
Type = type;
|
||||
Name = name;
|
||||
BuildType = null;
|
||||
BuildRequired = false;
|
||||
LifetimeManager = null;
|
||||
InjectionMembers = null;
|
||||
|
||||
Registration = null;
|
||||
ContainerContext = container.Context;
|
||||
|
||||
Seed = null;
|
||||
_enumerator = pipelines.GetEnumerator();
|
||||
}
|
||||
|
||||
public PipelineBuilder(Type type, string? name, UnityContainer container, IRegistration registration)
|
||||
{
|
||||
Seed = registration?.Pipeline;
|
||||
Type = type;
|
||||
Name = name;
|
||||
BuildType = registration.BuildType;
|
||||
BuildRequired = registration.BuildRequired;
|
||||
LifetimeManager = registration.LifetimeManager;
|
||||
InjectionMembers = registration.InjectionMembers;
|
||||
|
||||
Registration = registration;
|
||||
ContainerContext = container.Context;
|
||||
|
||||
Seed = registration.Pipeline;
|
||||
_enumerator = (registration?.Processors ??
|
||||
Enumerable.Empty<Pipeline>()).GetEnumerator();
|
||||
}
|
||||
|
@ -67,10 +84,15 @@ namespace Unity
|
|||
{
|
||||
Type = context.Type;
|
||||
Name = context.Name;
|
||||
BuildType = context.Registration?.BuildType;
|
||||
BuildRequired = context.Registration?.BuildRequired ?? false;
|
||||
LifetimeManager = context.Registration?.LifetimeManager;
|
||||
InjectionMembers = context.Registration?.InjectionMembers;
|
||||
|
||||
Registration = context.Registration;
|
||||
ContainerContext = context.ContainerContext;
|
||||
|
||||
Seed = Registration?.Pipeline;
|
||||
Seed = context.Registration?.Pipeline;
|
||||
_enumerator = (context.Registration?.Processors ??
|
||||
Enumerable.Empty<Pipeline>()).GetEnumerator();
|
||||
}
|
||||
|
@ -84,11 +106,21 @@ namespace Unity
|
|||
|
||||
public string? Name { get; }
|
||||
|
||||
public LifetimeManager? LifetimeManager { get; }
|
||||
|
||||
public InjectionMember[]? InjectionMembers { get; set; }
|
||||
|
||||
public bool BuildRequired { get; }
|
||||
|
||||
public Converter<Type, Type>? BuildType { get; }
|
||||
|
||||
|
||||
|
||||
public ResolveDelegate<BuilderContext>? Seed { get; private set; }
|
||||
|
||||
public readonly ContainerContext ContainerContext;
|
||||
|
||||
public readonly IRegistration? Registration;
|
||||
public IRegistration? Registration { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -113,35 +145,6 @@ namespace Unity
|
|||
: Seed;
|
||||
}
|
||||
|
||||
public PipelineDelegate PipelineDelegate()
|
||||
{
|
||||
var manager = Registration?.LifetimeManager;
|
||||
|
||||
return manager switch
|
||||
{
|
||||
null => TransientLifetime(),
|
||||
TransientLifetimeManager _ => TransientLifetime(),
|
||||
PerResolveLifetimeManager _ => PerResolveLifetime(),
|
||||
PerThreadLifetimeManager _ => PerThreadLifetime(),
|
||||
_ => DefaultLifetime()
|
||||
};
|
||||
}
|
||||
|
||||
public BuildPipelineAsync BuildPipelineAsync()
|
||||
{
|
||||
var manager = Registration?.LifetimeManager;
|
||||
|
||||
return manager switch
|
||||
{
|
||||
null => TransientLifetimeAsync(),
|
||||
TransientLifetimeManager _ => TransientLifetimeAsync(),
|
||||
PerResolveLifetimeManager _ => PerResolveLifetimeAsync(),
|
||||
PerThreadLifetimeManager _ => PerThreadLifetimeAsync(),
|
||||
_ => DefaultLifetimeAsync()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,7 @@ namespace Unity
|
|||
|
||||
// Try to get resolver
|
||||
Type? generic = null;
|
||||
var resolver = builder.Registration?.Pipeline ??
|
||||
builder.Registration?.Get(typeof(ResolveDelegate<BuilderContext>)) ??
|
||||
var resolver = builder.Registration?.Get(typeof(ResolveDelegate<BuilderContext>)) ??
|
||||
builder.ContainerContext.Get(builder.Type, typeof(ResolveDelegate<BuilderContext>));
|
||||
|
||||
if (null == resolver)
|
||||
|
@ -68,7 +67,7 @@ namespace Unity
|
|||
{
|
||||
if (builder.Type.GetArrayRank() == 1)
|
||||
{
|
||||
var resolve = ArrayResolver.Factory(builder.Type, builder.Registration);
|
||||
var resolve = ArrayResolver.Factory(builder.Type, (IRegistration)builder.Registration);
|
||||
return builder.Pipeline((ref BuilderContext context) => resolve(ref context));
|
||||
}
|
||||
else
|
||||
|
@ -104,7 +103,7 @@ namespace Unity
|
|||
Debug.Assert(null != builder.Type);
|
||||
|
||||
return null != factory
|
||||
? builder.Pipeline(factory(builder.Type, builder.Registration))
|
||||
? builder.Pipeline(factory(builder.Type, (IRegistration)builder.Registration))
|
||||
: builder.Pipeline();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,12 @@ namespace Unity
|
|||
else
|
||||
{
|
||||
// Implicit Registration
|
||||
if (null != builder.Registration.BuildType)
|
||||
builder.Type = builder.Registration.BuildType(builder.Type);
|
||||
if (null != builder.BuildType)
|
||||
builder.Type = builder.BuildType(builder.Type);
|
||||
}
|
||||
|
||||
// If nothing to map or build required, just create it
|
||||
if (builder.Registration.BuildRequired || requestedType == builder.Type)
|
||||
if (builder.BuildRequired || requestedType == builder.Type)
|
||||
return builder.Pipeline();
|
||||
|
||||
var type = builder.Type;
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace Unity
|
|||
}
|
||||
|
||||
// If nothing to map or build required, just create it
|
||||
if ((builder.Registration?.BuildRequired ?? false) || requestedType == builder.Type)
|
||||
if ((builder.BuildRequired) || requestedType == builder.Type)
|
||||
return builder.Pipeline();
|
||||
|
||||
var type = builder.Type;
|
||||
|
|
|
@ -202,35 +202,38 @@ namespace Unity
|
|||
|
||||
#region Getting objects
|
||||
|
||||
/*
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
object? IUnityContainer.Resolve(Type type, string? name, params ResolverOverride[] overrides)
|
||||
{
|
||||
var registration = GetRegistration(type ?? throw new ArgumentNullException(nameof(type)), name);
|
||||
var key = new HashKey(type ?? throw new ArgumentNullException(nameof(type)), name);
|
||||
var pipeline = GetPipeline(ref key);
|
||||
|
||||
// Check if already got value
|
||||
if (null != registration.LifetimeManager)
|
||||
// Check if already created and acquire a lock if not
|
||||
var manager = pipeline.Target as LifetimeManager;
|
||||
if (null != manager)
|
||||
{
|
||||
var value = registration.LifetimeManager.Get(LifetimeContainer);
|
||||
// Make blocking check for result
|
||||
var value = manager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
}
|
||||
|
||||
// Setup Context
|
||||
var synchronized = registration.LifetimeManager as SynchronizedLifetimeManager;
|
||||
var synchronized = manager as SynchronizedLifetimeManager;
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
Type = type,
|
||||
Overrides = overrides,
|
||||
Registration = registration,
|
||||
ContainerContext = Context,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
try
|
||||
{
|
||||
var value = context.Pipeline(ref context);
|
||||
registration.LifetimeManager?.Set(value, LifetimeContainer);
|
||||
var value = pipeline(ref context);
|
||||
manager?.Set(value, LifetimeContainer);
|
||||
return value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -247,6 +250,7 @@ namespace Unity
|
|||
else throw;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -294,5 +298,51 @@ namespace Unity
|
|||
IUnityContainer? IUnityContainer.Parent => _parent;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
[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
|
||||
if (null != registration.LifetimeManager)
|
||||
{
|
||||
var value = registration.LifetimeManager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
}
|
||||
|
||||
// Setup Context
|
||||
var synchronized = registration.LifetimeManager as SynchronizedLifetimeManager;
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
Type = type,
|
||||
Overrides = overrides,
|
||||
Registration = registration,
|
||||
ContainerContext = Context,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
try
|
||||
{
|
||||
var value = context.Pipeline(ref context);
|
||||
registration.LifetimeManager?.Set(value, LifetimeContainer);
|
||||
return value;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
synchronized?.Recover();
|
||||
|
||||
if (ex is InvalidRegistrationException ||
|
||||
ex is CircularDependencyException ||
|
||||
ex is ObjectDisposedException)
|
||||
{
|
||||
var message = CreateErrorMessage(ex);
|
||||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
}
|
||||
else throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,6 +188,9 @@ namespace Unity
|
|||
|
||||
#region Resolution
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
ValueTask<object?> IUnityContainerAsync.ResolveAsync(Type type, string? name, params ResolverOverride[] overrides)
|
||||
|
@ -248,9 +251,7 @@ namespace Unity
|
|||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*/
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
ValueTask<object?> IUnityContainerAsync.ResolveAsync(Type type, string? name, params ResolverOverride[] overrides)
|
||||
|
@ -300,14 +301,13 @@ namespace Unity
|
|||
ex is CircularDependencyException ||
|
||||
ex is ObjectDisposedException)
|
||||
{
|
||||
var message = CreateMessage(ex);
|
||||
var message = CreateErrorMessage(ex);
|
||||
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
|
||||
}
|
||||
else throw;
|
||||
}
|
||||
}));
|
||||
}
|
||||
*/
|
||||
|
||||
public ValueTask<IEnumerable<object>> Resolve(Type type, Regex regex, params ResolverOverride[] overrides)
|
||||
{
|
||||
|
|
|
@ -88,83 +88,86 @@ namespace Unity
|
|||
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey key, TypeInfo info)
|
||||
#else
|
||||
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey keyExact)
|
||||
#endif
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Debug.Assert(null != info);
|
||||
#else
|
||||
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey key)
|
||||
{
|
||||
#endif
|
||||
Debug.Assert(null != key.Type);
|
||||
|
||||
// bool initGenerics = true;
|
||||
// Type? generic = null;
|
||||
// int targetBucket;
|
||||
// var keyGeneric = new HashKey();
|
||||
// var keyDefault = new HashKey();
|
||||
int targetBucket;
|
||||
bool initGenerics = true;
|
||||
var keyGeneric = new HashKey();
|
||||
var keyDefault = new HashKey();
|
||||
Type type = key.Type;
|
||||
Type? generic = null;
|
||||
var name = key.Name;
|
||||
|
||||
// // Iterate through containers hierarchy
|
||||
// for (UnityContainer? container = this; null != container; container = container._parent)
|
||||
// {
|
||||
// // Skip to parent if no registrations
|
||||
// if (null == container._metadata) continue;
|
||||
// Iterate through containers hierarchy
|
||||
for (UnityContainer? container = this; null != container; container = container._parent)
|
||||
{
|
||||
// Skip to parent if no registrations
|
||||
if (null == container._metadata) continue;
|
||||
|
||||
// Debug.Assert(null != container._registry);
|
||||
// var registry = container._registry;
|
||||
Debug.Assert(null != container._registry);
|
||||
var registry = container._registry;
|
||||
|
||||
// // Check for exact match
|
||||
// targetBucket = keyExact.HashCode % registry.Buckets.Length;
|
||||
// for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
// {
|
||||
// ref var candidate = ref registry.Entries[i];
|
||||
// if (candidate.Key != keyExact) continue;
|
||||
// Check for exact match
|
||||
targetBucket = key.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != key) continue;
|
||||
|
||||
// // Found a registration
|
||||
// if (!(candidate.Policies is IRegistration))
|
||||
// candidate.Policies = container.CreateRegistration(type, name, candidate.Policies);
|
||||
Debug.Assert(null != candidate.Pipeline);
|
||||
|
||||
// Found a registration
|
||||
return candidate.Pipeline;
|
||||
}
|
||||
|
||||
// return ((IRegistration)candidate.Policies).Pipeline;
|
||||
// }
|
||||
// Generic registrations
|
||||
if (initGenerics)
|
||||
{
|
||||
initGenerics = false;
|
||||
|
||||
// // Generic registrations
|
||||
// if (initGenerics)
|
||||
// {
|
||||
// initGenerics = false;
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
generic = info.GetGenericTypeDefinition();
|
||||
#else
|
||||
generic = type.GetGenericTypeDefinition();
|
||||
#endif
|
||||
keyGeneric = new HashKey(generic, name);
|
||||
keyDefault = new HashKey(generic);
|
||||
}
|
||||
|
||||
//#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
// generic = info.GetGenericTypeDefinition();
|
||||
//#else
|
||||
// generic = type.GetGenericTypeDefinition();
|
||||
//#endif
|
||||
// keyGeneric = new HashKey(generic, name);
|
||||
// keyDefault = new HashKey(generic);
|
||||
// }
|
||||
// Check for factory with same name
|
||||
targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != keyGeneric)
|
||||
continue;
|
||||
|
||||
// // Check for factory with same name
|
||||
// targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
|
||||
// for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
// {
|
||||
// ref var candidate = ref registry.Entries[i];
|
||||
// if (candidate.Key != keyGeneric)
|
||||
// continue;
|
||||
// Found a factory
|
||||
return container.PipelineFromFactory(ref key, (IRegistration)candidate.Policies);
|
||||
}
|
||||
|
||||
// // Found a factory
|
||||
// return null;
|
||||
// }
|
||||
// Check for default factory
|
||||
targetBucket = keyDefault.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != keyDefault)
|
||||
continue;
|
||||
|
||||
// // Check for default factory
|
||||
// targetBucket = keyDefault.HashCode % registry.Buckets.Length;
|
||||
// for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
// {
|
||||
// ref var candidate = ref registry.Entries[i];
|
||||
// if (candidate.Key != keyDefault)
|
||||
// continue;
|
||||
// Found a factory
|
||||
return container.PipelineFromFactory(ref key, (IRegistration)candidate.Policies);
|
||||
}
|
||||
}
|
||||
|
||||
// // Found a factory
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
Debug.Assert(null != _root);
|
||||
|
||||
// Debug.Assert(null != _root);
|
||||
|
||||
// return null;
|
||||
return _root.PipelineFromType(ref key);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -174,6 +177,7 @@ namespace Unity
|
|||
|
||||
private ResolveDelegate<BuilderContext> PipelineFromType(ref HashKey key)
|
||||
{
|
||||
Debug.Assert(null != key.Type);
|
||||
Debug.Assert(null != _registry);
|
||||
|
||||
var type = key.Type;
|
||||
|
@ -307,6 +311,100 @@ namespace Unity
|
|||
};
|
||||
}
|
||||
|
||||
private ResolveDelegate<BuilderContext> PipelineFromFactory(ref HashKey key, IRegistration registration)
|
||||
{
|
||||
Debug.Assert(null != _registry);
|
||||
Debug.Assert(null != key.Type);
|
||||
|
||||
var type = key.Type;
|
||||
var name = key.Name;
|
||||
int count = -1;
|
||||
int position = 0;
|
||||
var collisions = 0;
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
|
||||
// Add Pipeline to the Registry
|
||||
lock (_syncLock)
|
||||
{
|
||||
var targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref _registry.Entries[i];
|
||||
if (candidate.Key != key)
|
||||
{
|
||||
collisions++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug.Assert(null != candidate.Pipeline);
|
||||
|
||||
// Has already been created
|
||||
return candidate.Pipeline;
|
||||
}
|
||||
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
{
|
||||
_registry = new Registry(_registry);
|
||||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Create new entry
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.Key = key;
|
||||
entry.Type = type;
|
||||
entry.Pipeline = BuildPipeline;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
position = _registry.Count++;
|
||||
_registry.Buckets[targetBucket] = position;
|
||||
}
|
||||
|
||||
// Return temporary pipeline
|
||||
return BuildPipeline;
|
||||
|
||||
|
||||
// Create pipeline and add to Registry
|
||||
object? BuildPipeline(ref BuilderContext context)
|
||||
{
|
||||
// Wait for right moment
|
||||
while (0 != Interlocked.Increment(ref count))
|
||||
{
|
||||
Interlocked.Decrement(ref count);
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
for (var i = 0; i < 100; i++) ;
|
||||
#else
|
||||
Thread.SpinWait(100);
|
||||
#endif
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Create if required
|
||||
if (null == pipeline)
|
||||
{
|
||||
//BuildType = factory.BuildType;
|
||||
//Next = factory.Next;
|
||||
//LifetimeManager = factory.LifetimeManager?.CreateLifetimePolicy();
|
||||
//Pipeline = factory.Pipeline;
|
||||
//InjectionMembers = factory.InjectionMembers;
|
||||
//BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired);
|
||||
|
||||
|
||||
PipelineBuilder builder = new PipelineBuilder(type, name, this, Context.TypePipelineCache);
|
||||
pipeline = builder.Pipeline();
|
||||
|
||||
Debug.Assert(null != pipeline);
|
||||
}
|
||||
|
||||
return pipeline(ref context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref count);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
|
|
Загрузка…
Ссылка в новой задаче