new registry
This commit is contained in:
Родитель
105c9a6cfe
Коммит
e0ea6e2cd5
|
@ -64,7 +64,9 @@ namespace Unity.Builder
|
|||
}
|
||||
}
|
||||
|
||||
return Resolve(type, name, (InternalRegistration)((UnityContainer)Container).GetRegistration(type, name));
|
||||
NamedType key = new NamedType { Name = name, Type = type };
|
||||
|
||||
return Resolve(type, name, (InternalRegistration)((UnityContainer)Container).GetRegistration(ref key));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Unity.Utility;
|
||||
|
||||
namespace Unity.Storage
|
||||
|
@ -12,6 +14,7 @@ namespace Unity.Storage
|
|||
private int[] Buckets;
|
||||
private Entry[] Entries;
|
||||
private int Count;
|
||||
public static readonly int[] Empty = new int[0];
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -76,14 +79,33 @@ namespace Unity.Storage
|
|||
|
||||
// Add new entry
|
||||
ref var entry = ref Entries[Count];
|
||||
entry.HashCode = hashCode;
|
||||
entry.Next = Buckets[targetBucket];
|
||||
entry.Key = key;
|
||||
entry.Count = 1;
|
||||
entry.Data = new int[] { value, -1 };
|
||||
entry.HashCode = hashCode;
|
||||
Buckets[targetBucket] = Count++;
|
||||
}
|
||||
|
||||
// TODO: Performance
|
||||
public IEnumerable<int> Get(Type key)
|
||||
{
|
||||
var hashCode = (key?.GetHashCode() ?? 0) & 0x7FFFFFFF;
|
||||
var targetBucket = hashCode % Buckets.Length;
|
||||
for (var i = Buckets[targetBucket]; i >= 0; i = Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref Entries[i];
|
||||
if (candidate.HashCode != hashCode || !Equals(candidate.Key, key)) continue;
|
||||
|
||||
var count = candidate.Count;
|
||||
var data = candidate.Data;
|
||||
|
||||
return data.Take(count);
|
||||
}
|
||||
|
||||
return Empty;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Utility;
|
||||
|
||||
|
@ -59,7 +59,7 @@ namespace Unity.Storage
|
|||
public int HashCode;
|
||||
public NamedType Key;
|
||||
public int Next;
|
||||
public IPolicySet Reference;
|
||||
public InternalRegistration Registration;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -44,20 +44,23 @@ namespace Unity
|
|||
var container = lifetimeManager is SingletonLifetimeManager ? _root : this;
|
||||
var registration = new ContainerRegistration(_validators, typeTo, (LifetimeManager)lifetimeManager, injectionMembers);
|
||||
|
||||
// If Disposable add to container's lifetime
|
||||
if (lifetimeManager is IDisposable disposableManager)
|
||||
container.LifetimeContainer.Add(disposableManager);
|
||||
|
||||
// Add or replace existing
|
||||
var previous = container.RegisterLegacy(registeredType, name, registration);
|
||||
if (previous is ContainerRegistration old &&
|
||||
old.LifetimeManager is IDisposable disposable)
|
||||
NamedType key = new NamedType { Name = name, Type = registeredType };
|
||||
var previous = container.Register(ref key, registration);
|
||||
|
||||
// Allow reference adjustment and disposal
|
||||
if (null != previous && 0 == previous.Release()
|
||||
&& previous.LifetimeManager is IDisposable disposable)
|
||||
{
|
||||
// Dispose replaced lifetime manager
|
||||
container.LifetimeContainer.Remove(disposable);
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
// If Disposable add to container's lifetime
|
||||
if (lifetimeManager is IDisposable disposableManager)
|
||||
container.LifetimeContainer.Add(disposableManager);
|
||||
|
||||
// Add Injection Members
|
||||
if (null != injectionMembers && injectionMembers.Length > 0)
|
||||
{
|
||||
|
@ -109,12 +112,12 @@ namespace Unity
|
|||
IUnityContainer IUnityContainer.RegisterInstance(Type type, string name, object instance, IInstanceLifetimeManager lifetimeManager)
|
||||
{
|
||||
var mappedToType = instance?.GetType();
|
||||
var typeFrom = type ?? mappedToType;
|
||||
var registeredType = type ?? mappedToType;
|
||||
|
||||
try
|
||||
{
|
||||
// Validate input
|
||||
if (null == typeFrom) throw new InvalidOperationException($"At least one of Type arguments '{nameof(type)}' or '{nameof(instance)}' must be not 'null'");
|
||||
if (null == registeredType) throw new InvalidOperationException($"At least one of Type arguments '{nameof(type)}' or '{nameof(instance)}' must be not 'null'");
|
||||
|
||||
if (null == lifetimeManager) lifetimeManager = new ContainerControlledLifetimeManager();
|
||||
if (((LifetimeManager)lifetimeManager).InUse) throw new InvalidOperationException(LifetimeManagerInUse);
|
||||
|
@ -124,26 +127,29 @@ namespace Unity
|
|||
var container = lifetimeManager is SingletonLifetimeManager ? _root : this;
|
||||
var registration = new ContainerRegistration(null, mappedToType, ((LifetimeManager)lifetimeManager));
|
||||
|
||||
// Add or replace existing
|
||||
var previous = container.RegisterLegacy(typeFrom, name, registration);
|
||||
if (previous is ContainerRegistration old &&
|
||||
old.LifetimeManager is IDisposable disposable)
|
||||
// If Disposable add to container's lifetime
|
||||
if (lifetimeManager is IDisposable manager)
|
||||
container.LifetimeContainer.Add(manager);
|
||||
|
||||
// Register type
|
||||
NamedType key = new NamedType { Name = name, Type = registeredType };
|
||||
var previous = container.Register(ref key, registration);
|
||||
|
||||
// Allow reference adjustment and disposal
|
||||
if (null != previous && 0 == previous.Release()
|
||||
&& previous.LifetimeManager is IDisposable disposable)
|
||||
{
|
||||
// Dispose replaced lifetime manager
|
||||
container.LifetimeContainer.Remove(disposable);
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
// If Disposable add to container's lifetime
|
||||
if (lifetimeManager is IDisposable manager)
|
||||
container.LifetimeContainer.Add(manager);
|
||||
|
||||
// Check what strategies to run
|
||||
registration.BuildChain = _strategiesChain.ToArray()
|
||||
.Where(strategy => strategy.RequiredToResolveInstance(this, registration))
|
||||
.ToArray();
|
||||
.Where(strategy => strategy.RequiredToResolveInstance(this, registration))
|
||||
.ToArray();
|
||||
// Raise event
|
||||
container.RegisteringInstance?.Invoke(this, new RegisterInstanceEventArgs(typeFrom, instance,
|
||||
container.RegisteringInstance?.Invoke(this, new RegisterInstanceEventArgs(registeredType, instance,
|
||||
name, ((LifetimeManager)lifetimeManager)));
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -153,7 +159,7 @@ namespace Unity
|
|||
if (null != name) parts.Add($" '{name}'");
|
||||
if (null != lifetimeManager && !(lifetimeManager is TransientLifetimeManager)) parts.Add(lifetimeManager.ToString());
|
||||
|
||||
var message = $"Error in RegisterInstance<{typeFrom?.Name}>({string.Join(", ", parts)})";
|
||||
var message = $"Error in RegisterInstance<{registeredType?.Name}>({string.Join(", ", parts)})";
|
||||
throw new InvalidOperationException(message, ex);
|
||||
}
|
||||
|
||||
|
@ -183,9 +189,12 @@ namespace Unity
|
|||
var registration = new ContainerRegistration(_validators, type, ((LifetimeManager)lifetimeManager), injectionMembers);
|
||||
|
||||
// Add or replace existing
|
||||
var previous = container.RegisterLegacy(type, name, registration);
|
||||
if (previous is ContainerRegistration old &&
|
||||
old.LifetimeManager is IDisposable disposable)
|
||||
NamedType key = new NamedType { Name = name, Type = type };
|
||||
var previous = container.Register(ref key, registration);
|
||||
|
||||
// Allow reference adjustment and disposal
|
||||
if (null != previous && 0 == previous.Release()
|
||||
&& previous.LifetimeManager is IDisposable disposable)
|
||||
{
|
||||
// Dispose replaced lifetime manager
|
||||
container.LifetimeContainer.Remove(disposable);
|
||||
|
@ -234,7 +243,8 @@ namespace Unity
|
|||
if (null == type) throw new ArgumentNullException(nameof(type));
|
||||
name = string.IsNullOrEmpty(name) ? null : name;
|
||||
|
||||
var registration = (InternalRegistration)GetRegistration(type, name);
|
||||
NamedType key = new NamedType { Name = name, Type = type };
|
||||
var registration = (InternalRegistration)GetRegistration(ref key);
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
|
@ -266,7 +276,8 @@ namespace Unity
|
|||
// Validate if they are assignable
|
||||
if (null != existing && null != TypeValidator) TypeValidator(type, existing.GetType());
|
||||
|
||||
var registration = (InternalRegistration)GetRegistration(type, name);
|
||||
NamedType key = new NamedType { Name = name, Type = type };
|
||||
var registration = (InternalRegistration)GetRegistration(ref key);
|
||||
var context = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
|
|
|
@ -100,6 +100,9 @@ namespace Unity
|
|||
var container = lifetimeManager is SingletonLifetimeManager ? _root : this;
|
||||
var registration = new ContainerRegistration(mappedToType, (LifetimeManager)lifetimeManager);
|
||||
|
||||
// If Disposable add to container's lifetime
|
||||
if (lifetimeManager is IDisposable manager) container.LifetimeContainer.Add(manager);
|
||||
|
||||
// Register interfaces
|
||||
var replaced = container.AddOrReplaceRegistrations(interfaces, name, registration)
|
||||
.ToArray();
|
||||
|
|
|
@ -54,11 +54,6 @@ namespace Unity
|
|||
private event EventHandler<ChildContainerCreatedEventArgs> ChildContainerCreated;
|
||||
|
||||
// Methods
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
internal Func<Type, string, IPolicySet> GetRegistration;
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
internal Func<Type, string, InternalRegistration, IPolicySet> RegisterLegacy;
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
internal GetPolicyDelegate GetPolicy;
|
||||
|
@ -107,7 +102,6 @@ namespace Unity
|
|||
IsTypeExplicitlyRegistered = _parent.IsTypeExplicitlyRegistered;
|
||||
|
||||
GetRegistration = _parent.GetRegistration;
|
||||
RegisterLegacy = CreateAndSetOrUpdate;
|
||||
GetPolicy = parent.GetPolicy;
|
||||
SetPolicy = CreateAndSetPolicy;
|
||||
ClearPolicy = delegate { };
|
||||
|
@ -256,13 +250,10 @@ namespace Unity
|
|||
_registrations = new Registrations(ContainerInitialCapacity);
|
||||
Set(null, null, Defaults);
|
||||
|
||||
RegisterLegacy = AddOrUpdateLegacy;
|
||||
GetPolicy = Get;
|
||||
SetPolicy = Set;
|
||||
ClearPolicy = Clear;
|
||||
|
||||
GetRegistration = GetDynamicRegistration;
|
||||
|
||||
_get = (type, name) => Get(type, name) ?? _parent._get(type, name);
|
||||
_getGenericRegistration = GetOrAddGeneric;
|
||||
IsTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
|
||||
|
|
|
@ -41,8 +41,6 @@ namespace Unity
|
|||
_isExplicitlyRegistered = IsExplicitlyRegisteredLocally;
|
||||
IsTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
|
||||
|
||||
GetRegistration = GetOrAdd;
|
||||
RegisterLegacy = AddOrUpdateLegacy;
|
||||
GetPolicy = Get;
|
||||
SetPolicy = Set;
|
||||
ClearPolicy = Clear;
|
||||
|
@ -81,7 +79,6 @@ namespace Unity
|
|||
|
||||
// Register this instance
|
||||
((IUnityContainer)this).RegisterInstance(typeof(IUnityContainer), null, this, new ContainerLifetimeManager());
|
||||
((IUnityContainerAsync)this).RegisterInstance(new[] { typeof(IUnityContainer) }, null, this, new ContainerLifetimeManager());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -23,7 +23,19 @@ namespace Unity
|
|||
|
||||
#region Delegates
|
||||
|
||||
private delegate IPolicySet RegisterDelegate(ref NamedType key, InternalRegistration registration);
|
||||
private delegate InternalRegistration RegisterDelegate(ref NamedType key, InternalRegistration registration);
|
||||
internal delegate InternalRegistration GetRegistrationDelegate(ref NamedType key);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Registration Methods
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private RegisterDelegate Register;
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
internal GetRegistrationDelegate GetRegistration;
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -31,8 +43,6 @@ namespace Unity
|
|||
#region Registration Fields
|
||||
|
||||
// Register single type
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private RegisterDelegate Register;
|
||||
|
||||
internal IPolicySet Defaults;
|
||||
private readonly object _syncRoot = new object();
|
||||
|
@ -191,40 +201,15 @@ namespace Unity
|
|||
var seed = null != container._parent ? GetRegistrations(container._parent)
|
||||
: new RegistrationSet();
|
||||
|
||||
if (null == container._registrations) return seed;
|
||||
if (null == container._registry) return seed;
|
||||
|
||||
var length = container._registrations.Count;
|
||||
var entries = container._registrations.Entries;
|
||||
var registry = container._registry;
|
||||
|
||||
for (var i = null == container._parent ? GetStartIndex() : 0; i < length; i++)
|
||||
for (var i = null == container._parent ? GetStartIndex() : 0; i < registry.Count; i++)
|
||||
{
|
||||
ref var entry = ref entries[i];
|
||||
var registry = entry.Value;
|
||||
|
||||
switch (registry)
|
||||
{
|
||||
case LinkedRegistry linkedRegistry:
|
||||
for (var node = (LinkedNode<string, IPolicySet>)linkedRegistry; null != node; node = node.Next)
|
||||
{
|
||||
if (node.Value is ContainerRegistration containerRegistration)
|
||||
seed.Add(entry.Key, node.Key, containerRegistration);
|
||||
}
|
||||
break;
|
||||
|
||||
case HashRegistry hashRegistry:
|
||||
var count = hashRegistry.Count;
|
||||
var nodes = hashRegistry.Entries;
|
||||
for (var j = 0; j < count; j++)
|
||||
{
|
||||
ref var refNode = ref nodes[j];
|
||||
if (refNode.Value is ContainerRegistration containerRegistration)
|
||||
seed.Add(entry.Key, refNode.Key, containerRegistration);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown type of registry");
|
||||
}
|
||||
ref var entry = ref registry.Entries[i];
|
||||
if (entry.Registration is ContainerRegistration containerRegistration)
|
||||
seed.Add(entry.Key.Type, entry.Key.Name, containerRegistration);
|
||||
}
|
||||
|
||||
return seed;
|
||||
|
@ -232,9 +217,9 @@ namespace Unity
|
|||
int GetStartIndex()
|
||||
{
|
||||
int start = -1;
|
||||
while (++start < length)
|
||||
while (++start < registry.Count)
|
||||
{
|
||||
if (typeof(IUnityContainer) != container._registrations.Entries[start].Key)
|
||||
if (typeof(IUnityContainer) != container._registry.Entries[start].Key.Type)
|
||||
continue;
|
||||
return start;
|
||||
}
|
||||
|
@ -248,36 +233,17 @@ namespace Unity
|
|||
var seed = null != container._parent ? GetRegistrations(container._parent, types)
|
||||
: new RegistrationSet();
|
||||
|
||||
if (null == container._registrations) return seed;
|
||||
if (null == container._registry) return seed;
|
||||
|
||||
var registry = container._registry;
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var registry = container.Get(type);
|
||||
if (null == registry?.Values) continue;
|
||||
|
||||
switch (registry)
|
||||
foreach (var i in container._metadata.Get(type))
|
||||
{
|
||||
case LinkedRegistry linkedRegistry:
|
||||
for (var node = (LinkedNode<string, IPolicySet>)linkedRegistry; null != node; node = node.Next)
|
||||
{
|
||||
if (node.Value is ContainerRegistration containerRegistration)
|
||||
seed.Add(type, node.Key, containerRegistration);
|
||||
}
|
||||
break;
|
||||
|
||||
case HashRegistry hashRegistry:
|
||||
var count = hashRegistry.Count;
|
||||
var nodes = hashRegistry.Entries;
|
||||
for (var j = 0; j < count; j++)
|
||||
{
|
||||
ref var refNode = ref nodes[j];
|
||||
if (refNode.Value is ContainerRegistration containerRegistration)
|
||||
seed.Add(type, refNode.Key, containerRegistration);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown type of registry");
|
||||
ref var entry = ref registry.Entries[i];
|
||||
if (entry.Registration is ContainerRegistration containerRegistration)
|
||||
seed.Add(entry.Key.Type, entry.Key.Name, containerRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,34 +257,15 @@ namespace Unity
|
|||
|
||||
if (null == container._registrations) return seed;
|
||||
|
||||
var registry = container._registry;
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var registry = container.Get(type);
|
||||
if (null == registry?.Values) continue;
|
||||
|
||||
switch (registry)
|
||||
foreach (var i in container._metadata.Get(type))
|
||||
{
|
||||
case LinkedRegistry linkedRegistry:
|
||||
for (var node = (LinkedNode<string, IPolicySet>)linkedRegistry; null != node; node = node.Next)
|
||||
{
|
||||
if (node.Value is ContainerRegistration containerRegistration && !string.IsNullOrEmpty(node.Key))
|
||||
seed.Add(type, node.Key, containerRegistration);
|
||||
}
|
||||
break;
|
||||
|
||||
case HashRegistry hashRegistry:
|
||||
var count = hashRegistry.Count;
|
||||
var nodes = hashRegistry.Entries;
|
||||
for (var j = 0; j < count; j++)
|
||||
{
|
||||
ref var refNode = ref nodes[j];
|
||||
if (refNode.Value is ContainerRegistration containerRegistration && !string.IsNullOrEmpty(refNode.Key))
|
||||
seed.Add(type, refNode.Key, containerRegistration);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException("Unknown type of registry");
|
||||
ref var entry = ref registry.Entries[i];
|
||||
if (entry.Registration is ContainerRegistration containerRegistration && !string.IsNullOrEmpty(entry.Key.Name))
|
||||
seed.Add(entry.Key.Type, entry.Key.Name, containerRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,8 +312,36 @@ namespace Unity
|
|||
: GetOrAddGeneric(type, name, info.GetGenericTypeDefinition());
|
||||
}
|
||||
|
||||
|
||||
private InternalRegistration CreateRegistration(ref NamedType key)
|
||||
{
|
||||
// TODO: Verify constructor
|
||||
var registration = new InternalRegistration(key.Type, key.Name);
|
||||
|
||||
if (key.Type.GetTypeInfo().IsGenericType)
|
||||
{
|
||||
var factory = (InternalRegistration)_get(key.Type.GetGenericTypeDefinition(), key.Name);
|
||||
if (null != factory)
|
||||
{
|
||||
registration.InjectionMembers = factory.InjectionMembers;
|
||||
registration.Map = factory.Map;
|
||||
var manager = factory.LifetimeManager;
|
||||
if (null != manager)
|
||||
{
|
||||
var policy = manager.CreateLifetimePolicy();
|
||||
registration.LifetimeManager = policy;
|
||||
if (policy is IDisposable) LifetimeContainer.Add(policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registration.BuildChain = GetBuilders(key.Type, registration);
|
||||
return registration;
|
||||
}
|
||||
|
||||
private IPolicySet CreateRegistration(Type type, string name)
|
||||
{
|
||||
// TODO: Verify constructor
|
||||
var registration = new InternalRegistration(type, name);
|
||||
|
||||
if (type.GetTypeInfo().IsGenericType)
|
||||
|
@ -405,8 +380,8 @@ namespace Unity
|
|||
private IEnumerable<IPolicySet> AddOrReplaceRegistrations(IEnumerable<Type> interfaces, string name, ContainerRegistration registration)
|
||||
{
|
||||
NamedType key;
|
||||
int count = 0;
|
||||
|
||||
int count = 0;
|
||||
key.Name = name;
|
||||
|
||||
if (null != interfaces)
|
||||
|
@ -418,16 +393,7 @@ namespace Unity
|
|||
|
||||
// Add or replace existing
|
||||
var previous = Register(ref key, registration);
|
||||
|
||||
// Add reference count
|
||||
registration.AddRef();
|
||||
|
||||
// Allow reference adjustment and disposal
|
||||
if (previous is ContainerRegistration old &&
|
||||
old.LifetimeManager is IDisposable disposable)
|
||||
{
|
||||
yield return previous;
|
||||
}
|
||||
if (null != previous) yield return previous;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
@ -443,20 +409,16 @@ namespace Unity
|
|||
|
||||
// Add or replace existing
|
||||
var previous = Register(ref key, registration);
|
||||
|
||||
// Add reference count
|
||||
registration.AddRef();
|
||||
|
||||
// Allow reference adjustment and disposal
|
||||
if (previous is ContainerRegistration old &&
|
||||
old.LifetimeManager is IDisposable disposable)
|
||||
{
|
||||
yield return previous;
|
||||
}
|
||||
if (null != previous) yield return previous;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Legacy
|
||||
|
||||
private IPolicySet AddOrUpdateLegacy(Type type, string name, InternalRegistration registration)
|
||||
{
|
||||
var collisions = 0;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Unity.Policy;
|
||||
using System.Diagnostics;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
|
@ -7,6 +7,13 @@ namespace Unity
|
|||
{
|
||||
public partial class UnityContainer
|
||||
{
|
||||
#region Constants
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private const int CollisionsCutPoint = 5;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
private Registry _registry;
|
||||
|
@ -15,9 +22,9 @@ namespace Unity
|
|||
#endregion
|
||||
|
||||
|
||||
#region
|
||||
#region Registrations Manipulation
|
||||
|
||||
private IPolicySet InitAndAdd(ref NamedType key, InternalRegistration registration)
|
||||
private InternalRegistration InitAndAdd(ref NamedType key, InternalRegistration registration)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
|
@ -27,15 +34,16 @@ namespace Unity
|
|||
_metadata = new Metadata();
|
||||
|
||||
Register = AddOrReplace;
|
||||
GetRegistration = GetOrAdd;
|
||||
}
|
||||
}
|
||||
|
||||
return Register(ref key, registration);
|
||||
}
|
||||
|
||||
private IPolicySet AddOrReplace(ref NamedType key, InternalRegistration registration)
|
||||
private InternalRegistration AddOrReplace(ref NamedType key, InternalRegistration registration)
|
||||
{
|
||||
var hashCode = key.GetHashCode();
|
||||
var hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
||||
var targetBucket = hashCode % _registry.Buckets.Length;
|
||||
var collisions = 0;
|
||||
|
||||
|
@ -51,24 +59,30 @@ namespace Unity
|
|||
continue;
|
||||
}
|
||||
|
||||
var existing = candidate.Reference;
|
||||
// Replace registration
|
||||
var existing = candidate.Registration;
|
||||
|
||||
candidate.Reference = registration;
|
||||
candidate.Registration = registration;
|
||||
candidate.Registration.AddRef();
|
||||
|
||||
return existing;
|
||||
}
|
||||
|
||||
if (_registry.RequireToGrow || ListToHashCutPoint < collisions)
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
{
|
||||
_registry = new Registry(_registry);
|
||||
targetBucket = hashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Add registration
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.HashCode = hashCode;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
entry.Key = key;
|
||||
entry.Reference = registration;
|
||||
entry.Registration = registration;
|
||||
entry.Registration.AddRef();
|
||||
|
||||
var position = _registry.Count++;
|
||||
_registry.Buckets[targetBucket] = position;
|
||||
_metadata.Add(key.Type, position);
|
||||
|
@ -77,6 +91,64 @@ namespace Unity
|
|||
}
|
||||
}
|
||||
|
||||
private InternalRegistration GetOrAdd(ref NamedType key)
|
||||
{
|
||||
var hashCode = key.GetHashCode() & 0x7FFFFFFF;
|
||||
var targetBucket = hashCode % _registry.Buckets.Length;
|
||||
var registry = _registry;
|
||||
|
||||
// Check for existing without squaring the lock first
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.HashCode != hashCode ||
|
||||
candidate.Key.Type != key.Type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found a registration
|
||||
return candidate.Registration;
|
||||
}
|
||||
|
||||
// Nothing found so get the lock and add a new registration
|
||||
|
||||
// Do the double-check lock to verify it was not yet added
|
||||
lock (_syncRoot)
|
||||
{
|
||||
var collisions = 0;
|
||||
|
||||
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.HashCode != hashCode ||
|
||||
candidate.Key.Type != key.Type)
|
||||
{
|
||||
collisions++;
|
||||
continue;
|
||||
}
|
||||
|
||||
return candidate.Registration;
|
||||
}
|
||||
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
{
|
||||
_registry = new Registry(_registry);
|
||||
targetBucket = hashCode % _registrations.Buckets.Length;
|
||||
}
|
||||
|
||||
// Add registration
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.HashCode = hashCode;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
entry.Key = key;
|
||||
entry.Registration = CreateRegistration(ref key);
|
||||
entry.Registration.AddRef();
|
||||
_registry.Buckets[targetBucket] = _registry.Count++;
|
||||
|
||||
return entry.Registration;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче