This commit is contained in:
Eugene Sadovoi 2019-06-02 19:48:58 -04:00
Родитель 25528874c6
Коммит eb6e5ef941
12 изменённых файлов: 268 добавлений и 596 удалений

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

@ -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