Fixed non async tests
This commit is contained in:
Родитель
55e5eff24f
Коммит
d48e431cb6
|
@ -22,7 +22,7 @@ namespace Unity.Registration
|
|||
|
||||
Converter<Type, Type>? BuildType { get; }
|
||||
|
||||
LifetimeManager? LifetimeManager { get; }
|
||||
LifetimeManager LifetimeManager { get; }
|
||||
|
||||
UnityContainer Owner { get; }
|
||||
}
|
||||
|
|
|
@ -19,17 +19,15 @@ namespace Unity.Registration
|
|||
{
|
||||
Next = null;
|
||||
Type = type;
|
||||
LifetimeManager = new TransientLifetimeManager();
|
||||
InjectionMembers = null;
|
||||
BuildRequired = false;
|
||||
}
|
||||
|
||||
public ExplicitRegistration(UnityContainer owner, string? name, Type? type, LifetimeManager lifetimeManager)
|
||||
: base(owner, name)
|
||||
: base(owner, name, lifetimeManager)
|
||||
{
|
||||
Next = null;
|
||||
Type = type;
|
||||
LifetimeManager = lifetimeManager;
|
||||
InjectionMembers = null;
|
||||
BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired);
|
||||
|
||||
|
@ -38,10 +36,9 @@ namespace Unity.Registration
|
|||
}
|
||||
|
||||
public ExplicitRegistration(UnityContainer owner, string? name, Type? type, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
|
||||
: base(owner, name)
|
||||
: base(owner, name, lifetimeManager)
|
||||
{
|
||||
Type = type;
|
||||
LifetimeManager = lifetimeManager;
|
||||
Next = owner.Defaults;
|
||||
InjectionMembers = null != injectionMembers && 0 < injectionMembers.Length ? injectionMembers : null;
|
||||
BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired) || lifetimeManager is PerResolveLifetimeManager;
|
||||
|
|
|
@ -12,7 +12,7 @@ using Unity.Storage;
|
|||
|
||||
namespace Unity.Registration
|
||||
{
|
||||
[DebuggerDisplay("Registration.Implicit({Count})")]
|
||||
//[DebuggerDisplay("Registration.Implicit({Count})")]
|
||||
//[DebuggerTypeProxy(typeof(ImplicitRegistrationDebugProxy))]
|
||||
public class ImplicitRegistration : PolicySet, IRegistration
|
||||
{
|
||||
|
@ -26,17 +26,19 @@ namespace Unity.Registration
|
|||
|
||||
#region Constructors
|
||||
|
||||
public ImplicitRegistration(UnityContainer owner, string? name)
|
||||
public ImplicitRegistration(UnityContainer owner, string? name, LifetimeManager? manager = null)
|
||||
: base(owner)
|
||||
{
|
||||
Name = name;
|
||||
LifetimeManager = manager ?? new TransientLifetimeManager();
|
||||
}
|
||||
|
||||
public ImplicitRegistration(UnityContainer owner, string? name, IPolicySet? set)
|
||||
public ImplicitRegistration(UnityContainer owner, string? name, LifetimeManager manager, IPolicySet? set)
|
||||
: base(owner)
|
||||
{
|
||||
Name = name;
|
||||
Next = (PolicyEntry?)set;
|
||||
LifetimeManager = manager;
|
||||
}
|
||||
|
||||
public ImplicitRegistration(UnityContainer owner, string? name, ImplicitRegistration factory)
|
||||
|
@ -45,17 +47,18 @@ namespace Unity.Registration
|
|||
Name = name;
|
||||
BuildType = factory.BuildType;
|
||||
Next = factory.Next;
|
||||
LifetimeManager = factory.LifetimeManager?.CreateLifetimePolicy();
|
||||
LifetimeManager = factory.LifetimeManager?.CreateLifetimePolicy() ?? new TransientLifetimeManager();
|
||||
Pipeline = factory.Pipeline;
|
||||
InjectionMembers = factory.InjectionMembers;
|
||||
BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired);
|
||||
}
|
||||
|
||||
public ImplicitRegistration(UnityContainer owner, string? name, ResolveDelegate<BuilderContext> pipeline)
|
||||
public ImplicitRegistration(UnityContainer owner, string? name, LifetimeManager manager, ResolveDelegate<BuilderContext> pipeline)
|
||||
: base(owner)
|
||||
{
|
||||
Name = name;
|
||||
Pipeline = pipeline;
|
||||
LifetimeManager = manager;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -75,7 +78,7 @@ namespace Unity.Registration
|
|||
|
||||
public virtual Converter<Type, Type>? BuildType { get; }
|
||||
|
||||
public LifetimeManager? LifetimeManager { get; protected set; }
|
||||
public LifetimeManager LifetimeManager { get; protected set; }
|
||||
|
||||
public virtual void Add(IPolicySet set)
|
||||
{
|
||||
|
|
|
@ -191,7 +191,6 @@ namespace Unity
|
|||
|
||||
|
||||
|
||||
/*
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
ValueTask<object?> IUnityContainerAsync.ResolveAsync(Type type, string? name, params ResolverOverride[] overrides)
|
||||
|
@ -252,64 +251,6 @@ 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);
|
||||
|
||||
if (null != registration.LifetimeManager)
|
||||
{
|
||||
// Make unblocking check if already has result
|
||||
var value = registration.LifetimeManager.TryGet(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
|
||||
return new ValueTask<object?>(Task.Factory.StartNew<object?>(delegate
|
||||
{
|
||||
// Check if already created and acquire a lock
|
||||
if (null != registration.LifetimeManager)
|
||||
{
|
||||
var value = registration.LifetimeManager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
// Setup Context
|
||||
var synchronized = registration.LifetimeManager as SynchronizedLifetimeManager;
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
Type = type,
|
||||
Name = name,
|
||||
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;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public ValueTask<IEnumerable<object>> Resolve(Type type, Regex regex, params ResolverOverride[] overrides)
|
||||
{
|
||||
|
|
|
@ -20,25 +20,9 @@ namespace Unity
|
|||
var name = key.Name;
|
||||
var owner = this;
|
||||
|
||||
int count = -1;
|
||||
int position = 0;
|
||||
var collisions = 0;
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
ResolveDelegate<BuilderContext> buildPipeline;
|
||||
var manager = null != factory.LifetimeManager && !(factory.LifetimeManager is TransientLifetimeManager)
|
||||
? factory.LifetimeManager.CreateLifetimePolicy()
|
||||
: null;
|
||||
|
||||
if (null != manager)
|
||||
{
|
||||
if (manager is IDisposable disposable) Context.Lifetime.Add(disposable);
|
||||
if (manager is ContainerControlledLifetimeManager containerControlled) containerControlled.Scope = Context;
|
||||
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)BuildPipeline;
|
||||
buildPipeline = manager.Pipeline;
|
||||
}
|
||||
else
|
||||
buildPipeline = BuildPipeline;
|
||||
LifetimeManager manager;
|
||||
|
||||
// Add Pipeline to the Registry
|
||||
lock (_syncLock)
|
||||
|
@ -53,9 +37,8 @@ namespace Unity
|
|||
continue;
|
||||
}
|
||||
|
||||
Debug.Assert(null != candidate.Pipeline);
|
||||
|
||||
// Has already been created
|
||||
Debug.Assert(null != candidate.Pipeline);
|
||||
return candidate.Pipeline;
|
||||
}
|
||||
|
||||
|
@ -66,53 +49,187 @@ namespace Unity
|
|||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Create a Lifetime Manager
|
||||
manager = factory.LifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = manager switch
|
||||
{
|
||||
TransientLifetimeManager transient => PipelineFromOpenGenericTransient(type, factory, transient, _registry.Count),
|
||||
SynchronizedLifetimeManager synch => PipelineFromOpenGenericSynchronized(type, factory, synch),
|
||||
PerResolveLifetimeManager peresolve => PipelineFromOpenGenericPerResolve(type, factory, peresolve),
|
||||
_ => PipelineFromOpenGenericDefault(type, factory, manager)
|
||||
};
|
||||
|
||||
// Create new entry
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.Key = key;
|
||||
entry.Type = type;
|
||||
entry.Pipeline = buildPipeline;
|
||||
entry.Pipeline = manager.Pipeline;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
position = _registry.Count++;
|
||||
_registry.Buckets[targetBucket] = position;
|
||||
}
|
||||
|
||||
// Return temporary pipeline
|
||||
return buildPipeline;
|
||||
if (manager is IDisposable disposable) Context.Lifetime.Add(disposable);
|
||||
|
||||
// Return pipeline
|
||||
return manager.Pipeline;
|
||||
}
|
||||
|
||||
// Create pipeline and add to Registry
|
||||
object? BuildPipeline(ref BuilderContext context)
|
||||
private ResolveDelegate<BuilderContext> PipelineFromOpenGenericTransient(Type type, ExplicitRegistration factory, TransientLifetimeManager manager, int position)
|
||||
{
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
|
||||
return (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
|
||||
}
|
||||
if (null != pipeline) return pipeline(ref context);
|
||||
|
||||
try
|
||||
lock (manager)
|
||||
{
|
||||
// Create if required
|
||||
if (null == pipeline)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, owner);
|
||||
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, this);
|
||||
pipeline = builder.Pipeline();
|
||||
if (null != manager) manager.PipelineDelegate = pipeline;
|
||||
|
||||
Debug.Assert(null != pipeline);
|
||||
Debug.Assert(null != _registry);
|
||||
|
||||
// Replace pipeline in storage
|
||||
lock (_syncLock)
|
||||
{
|
||||
_registry.Entries[position].Pipeline = pipeline;
|
||||
}
|
||||
}
|
||||
|
||||
var value = pipeline(ref context);
|
||||
manager?.Set(value, LifetimeContainer);
|
||||
return value;
|
||||
return pipeline(ref context);
|
||||
}
|
||||
finally
|
||||
};
|
||||
}
|
||||
|
||||
private ResolveDelegate<BuilderContext> PipelineFromOpenGenericSynchronized(Type type, ExplicitRegistration factory, SynchronizedLifetimeManager manager)
|
||||
{
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
object value;
|
||||
|
||||
if (null != pipeline)
|
||||
{
|
||||
Interlocked.Decrement(ref count);
|
||||
value = manager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
return pipeline(ref context);
|
||||
}
|
||||
|
||||
lock (manager)
|
||||
{
|
||||
if (null == pipeline)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, this);
|
||||
|
||||
pipeline = builder.Pipeline();
|
||||
manager.PipelineDelegate = pipeline;
|
||||
|
||||
Debug.Assert(null != pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
value = manager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
try
|
||||
{
|
||||
// Build withing the scope
|
||||
return pipeline(ref context);
|
||||
}
|
||||
catch
|
||||
{
|
||||
manager.Recover();
|
||||
throw;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ResolveDelegate<BuilderContext> PipelineFromOpenGenericPerResolve(Type type, ExplicitRegistration factory, PerResolveLifetimeManager manager)
|
||||
{
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
object value;
|
||||
LifetimeManager? lifetime;
|
||||
|
||||
if (null != pipeline)
|
||||
{
|
||||
if (null != (lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager))))
|
||||
{
|
||||
value = lifetime.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
}
|
||||
|
||||
return pipeline(ref context);
|
||||
}
|
||||
|
||||
lock (manager)
|
||||
{
|
||||
if (null == pipeline)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, this);
|
||||
|
||||
pipeline = builder.Pipeline();
|
||||
manager.PipelineDelegate = pipeline;
|
||||
|
||||
Debug.Assert(null != pipeline);
|
||||
|
||||
value = pipeline(ref context);
|
||||
context.Set(typeof(LifetimeManager), new RuntimePerResolveLifetimeManager(value));
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
if (null != (lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager))))
|
||||
{
|
||||
value = lifetime.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
}
|
||||
|
||||
return pipeline(ref context);
|
||||
};
|
||||
}
|
||||
|
||||
private ResolveDelegate<BuilderContext> PipelineFromOpenGenericDefault(Type type, ExplicitRegistration factory, LifetimeManager manager)
|
||||
{
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
object value;
|
||||
|
||||
if (null != pipeline)
|
||||
{
|
||||
value = manager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
return pipeline(ref context);
|
||||
}
|
||||
|
||||
lock (manager)
|
||||
{
|
||||
if (null == pipeline)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, this);
|
||||
|
||||
pipeline = builder.Pipeline();
|
||||
manager.PipelineDelegate = pipeline;
|
||||
|
||||
Debug.Assert(null != pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
value = manager.Get(LifetimeContainer);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
return pipeline(ref context);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace Unity
|
|||
{
|
||||
Debug.Assert(null != _registry);
|
||||
Debug.Assert(null != key.Type);
|
||||
Debug.Assert(null != registration.LifetimeManager);
|
||||
|
||||
registration.LifetimeManager.PipelineDelegate = registration.LifetimeManager switch
|
||||
{
|
||||
|
|
|
@ -56,7 +56,6 @@ namespace Unity
|
|||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
|
||||
// Create a Lifetime Manager
|
||||
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = manager switch
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Storage;
|
||||
|
||||
|
@ -41,134 +37,6 @@ namespace Unity
|
|||
#endregion
|
||||
|
||||
|
||||
#region Getting Registration During Resolution
|
||||
|
||||
internal IRegistration GetRegistration(Type type, string? name)
|
||||
{
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
var info = type.GetTypeInfo();
|
||||
return info.IsGenericType ? GetGenericRegistration(type, name, info) : GetSimpleRegistration(type, name);
|
||||
#else
|
||||
return type.IsGenericType ? GetGenericRegistration(type, name) : GetSimpleRegistration(type, name);
|
||||
#endif
|
||||
}
|
||||
|
||||
private IRegistration GetSimpleRegistration(Type type, string? name)
|
||||
{
|
||||
var key = new HashKey(type, 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;
|
||||
|
||||
Debug.Assert(null != container._registry);
|
||||
var registry = container._registry;
|
||||
|
||||
// Check for exact match
|
||||
for (var i = registry.Buckets[key.HashCode % registry.Buckets.Length]; 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);
|
||||
|
||||
return (IRegistration)candidate.Policies;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(null != _root);
|
||||
|
||||
return _root.GetOrAdd(ref key, type, name, null);
|
||||
}
|
||||
|
||||
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
private IRegistration GetGenericRegistration(Type type, string? name, TypeInfo info)
|
||||
#else
|
||||
private IRegistration GetGenericRegistration(Type type, string? name)
|
||||
#endif
|
||||
{
|
||||
bool initGenerics = true;
|
||||
Type? generic = null;
|
||||
int targetBucket;
|
||||
var keyExact = new HashKey(type, name);
|
||||
var keyGeneric = new HashKey();
|
||||
var keyDefault = new HashKey();
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Found a registration
|
||||
if (!(candidate.Policies is IRegistration))
|
||||
candidate.Policies = container.CreateRegistration(type, name, candidate.Policies);
|
||||
|
||||
return (IRegistration)candidate.Policies;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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.GetOrAdd(ref keyExact, type, name, candidate.Policies);
|
||||
}
|
||||
|
||||
// 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.GetOrAdd(ref keyExact, type, name, candidate.Policies);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(null != _root);
|
||||
|
||||
return _root.GetOrAdd(ref keyExact, type, name, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Registration manipulation
|
||||
|
||||
private ExplicitRegistration? InitAndAdd(Type type, string? name, ExplicitRegistration registration)
|
||||
|
@ -295,75 +163,6 @@ namespace Unity
|
|||
return null;
|
||||
}
|
||||
|
||||
private IEnumerable<IPolicySet> AddOrReplace(IEnumerable<Type> type, string? name, ExplicitRegistration registration)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private IRegistration GetOrAdd(ref HashKey key, Type type, string? name, IPolicySet? factory = null)
|
||||
{
|
||||
Debug.Assert(null != _registry);
|
||||
|
||||
lock (_syncLock)
|
||||
{
|
||||
var collisions = 0;
|
||||
var targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
|
||||
// Check for the existing
|
||||
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;
|
||||
}
|
||||
|
||||
if (!(candidate.Policies is IRegistration))
|
||||
candidate.Policies = CreateRegistration(type, name, candidate.Policies);
|
||||
|
||||
return (IRegistration)candidate.Policies;
|
||||
}
|
||||
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
{
|
||||
_registry = new Registry(_registry);
|
||||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Add registration
|
||||
var registration = CreateRegistration(type, name, factory);
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.Key = key;
|
||||
entry.Type = type;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
entry.Policies = registration;
|
||||
_registry.Buckets[targetBucket] = _registry.Count++;
|
||||
|
||||
return (IRegistration)entry.Policies;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Creating Implicit Registration
|
||||
|
||||
private IRegistration CreateRegistration(Type type, string? name, IPolicySet? set)
|
||||
{
|
||||
var registration = set is ImplicitRegistration factory
|
||||
? new ImplicitRegistration(this, name, factory)
|
||||
: new ImplicitRegistration(this, name, set);
|
||||
|
||||
registration.Processors = Context.TypePipelineCache;
|
||||
|
||||
if (registration.LifetimeManager is IDisposable) LifetimeContainer.Add(registration.LifetimeManager);
|
||||
if (registration.LifetimeManager is ContainerControlledLifetimeManager manager) manager.Scope = this.Context;
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace Unity
|
|||
|
||||
#region Resolving Enumerable
|
||||
|
||||
internal IEnumerable<TElement> ResolveEnumerable<TElement>(Func<Type, IRegistration, object?> resolve, string? name)
|
||||
internal IEnumerable<TElement> ResolveEnumerable<TElement>(Func<Type, string?, object?> resolve, string? name)
|
||||
{
|
||||
object? value;
|
||||
var set = new QuickSet();
|
||||
|
@ -104,7 +104,7 @@ namespace Unity
|
|||
|
||||
try
|
||||
{
|
||||
value = resolve(typeof(TElement), registration);
|
||||
value = resolve(typeof(TElement), registration.Name);
|
||||
}
|
||||
catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
|
||||
{
|
||||
|
@ -123,8 +123,7 @@ namespace Unity
|
|||
{
|
||||
try
|
||||
{
|
||||
var registration = GetRegistration(typeof(TElement), name);
|
||||
value = resolve(typeof(TElement), registration);
|
||||
value = resolve(typeof(TElement), name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -137,7 +136,7 @@ namespace Unity
|
|||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<TElement> ResolveEnumerable<TElement>(Func<Type, IRegistration, object?> resolve,
|
||||
internal IEnumerable<TElement> ResolveEnumerable<TElement>(Func<Type, string?, object?> resolve,
|
||||
Type typeDefinition, string? name)
|
||||
{
|
||||
object? value;
|
||||
|
@ -168,7 +167,7 @@ namespace Unity
|
|||
|
||||
try
|
||||
{
|
||||
value = resolve(typeof(TElement), registration);
|
||||
value = resolve(typeof(TElement), registration.Name);
|
||||
}
|
||||
catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
|
||||
{
|
||||
|
@ -194,9 +193,7 @@ namespace Unity
|
|||
{
|
||||
try
|
||||
{
|
||||
var itemKey = new HashKey(typeof(TElement), registration.Name);
|
||||
var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration);
|
||||
value = resolve(typeof(TElement), item);
|
||||
value = resolve(typeof(TElement), registration.Name);
|
||||
}
|
||||
catch (MakeGenericTypeFailedException) { continue; }
|
||||
catch (InvalidRegistrationException) { continue; }
|
||||
|
@ -214,8 +211,7 @@ namespace Unity
|
|||
{
|
||||
try
|
||||
{
|
||||
var registration = GetRegistration(typeof(TElement), name);
|
||||
value = resolve(typeof(TElement), registration);
|
||||
value = resolve(typeof(TElement), name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче