This commit is contained in:
Eugene Sadovoi 2019-04-08 00:10:18 -04:00
Родитель ec39834140
Коммит 9ad7e68bee
18 изменённых файлов: 725 добавлений и 117 удалений

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

@ -0,0 +1,7 @@
using System.Threading.Tasks;
using Unity.Resolution;
namespace Unity.Abstracts
{
public delegate Task<object> PipelineDelegate(IUnityContainer container, params ResolverOverride[] overrides);
}

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

@ -11,6 +11,27 @@ namespace Unity.Registration
{ {
#region Constructors #region Constructors
public ContainerRegistration(Type mappedTo, LifetimeManager lifetimeManager, InjectionMember[] injectionMembers = null)
{
Type = mappedTo;
Key = typeof(LifetimeManager);
Value = lifetimeManager;
LifetimeManager.InUse = true;
InjectionMembers = injectionMembers;
Next = null;
}
public ContainerRegistration(LinkedNode<Type, object> validators, LifetimeManager lifetimeManager, InjectionMember[] injectionMembers = null)
{
Type = null;
Key = typeof(LifetimeManager);
Value = lifetimeManager;
LifetimeManager.InUse = true;
InjectionMembers = injectionMembers;
Next = validators;
}
public ContainerRegistration(LinkedNode<Type, object> validators, Type mappedTo, LifetimeManager lifetimeManager, InjectionMember[] injectionMembers = null) public ContainerRegistration(LinkedNode<Type, object> validators, Type mappedTo, LifetimeManager lifetimeManager, InjectionMember[] injectionMembers = null)
{ {
Type = mappedTo; Type = mappedTo;
@ -32,13 +53,6 @@ namespace Unity.Registration
/// </summary> /// </summary>
public Type Type { get; } public Type Type { get; }
/// <summary>
/// The lifetime manager for this registration.
/// </summary>
/// <remarks>
/// This property will be null if this registration is for an open generic.</remarks>
public LifetimeManager LifetimeManager => (LifetimeManager)Value;
#endregion #endregion
} }
} }

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

@ -1,6 +1,8 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Threading;
using Unity.Injection; using Unity.Injection;
using Unity.Lifetime;
using Unity.Policy; using Unity.Policy;
using Unity.Storage; using Unity.Storage;
using Unity.Strategies; using Unity.Strategies;
@ -11,16 +13,28 @@ namespace Unity.Registration
public class InternalRegistration : LinkedNode<Type, object>, public class InternalRegistration : LinkedNode<Type, object>,
IPolicySet IPolicySet
{ {
#region Fields
private int _refCount;
#endregion
#region Constructors #region Constructors
public InternalRegistration() public InternalRegistration()
{ {
Key = typeof(LifetimeManager);
} }
public InternalRegistration(Type policyInterface, object policy) public InternalRegistration(Type policyInterface, object policy)
{ {
Key = policyInterface; Key = typeof(LifetimeManager);
Value = policy; Next = new LinkedNode<Type, object>
{
Key = policyInterface,
Value = policy,
Next = Next
};
} }
#endregion #endregion
@ -36,6 +50,17 @@ namespace Unity.Registration
public Converter<Type, Type> Map { get; set; } public Converter<Type, Type> Map { get; set; }
// TODO: Streamline LifetimeManager usage
public LifetimeManager LifetimeManager
{
get => (LifetimeManager)Value;
set => Value = value;
}
public virtual int AddRef() => Interlocked.Increment(ref _refCount);
public virtual int Release() => Interlocked.Decrement(ref _refCount);
#endregion #endregion
@ -54,20 +79,12 @@ namespace Unity.Registration
public virtual void Set(Type policyInterface, object policy) public virtual void Set(Type policyInterface, object policy)
{ {
if (null == Value && null == Key) Next = new LinkedNode<Type, object>
{ {
Key = policyInterface; Key = policyInterface,
Value = policy; Value = policy,
} Next = Next
else };
{
Next = new LinkedNode<Type, object>
{
Key = policyInterface,
Value = policy,
Next = Next
};
}
} }
public virtual void Clear(Type policyInterface) public virtual void Clear(Type policyInterface)

104
src/Storage/Metadata.cs Normal file
Просмотреть файл

@ -0,0 +1,104 @@
using System;
using System.Diagnostics;
using Unity.Utility;
namespace Unity.Storage
{
[DebuggerDisplay("Metadata ({Count}) ")]
internal class Metadata
{
#region Fields
private int[] Buckets;
private Entry[] Entries;
private int Count;
#endregion
#region Constructors
public Metadata()
{
Buckets = new int[37];
Entries = new Entry[37];
HashHelpers.FillArray(Buckets, -1);
}
#endregion
#region Public Members
public void Add(Type key, int value)
{
// Check for existing
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;
if (candidate.Data.Length == candidate.Count)
{
var source = candidate.Data;
candidate.Data = new int[2 * candidate.Data.Length];
Array.Copy(source, 0, candidate.Data, 0, candidate.Count);
}
candidate.Data[candidate.Count++] = value;
}
// Grow if required
if ((Entries.Length - Count) < 100 && (float)Count / Entries.Length > 0.72f)
{
var entries = Entries;
var size = HashHelpers.GetPrime(2 * Buckets.Length);
Buckets = new int[size];
Entries = new Entry[size];
HashHelpers.FillArray(Buckets, -1);
Array.Copy(entries, 0, Entries, 0, Count);
for (var i = 0; i < Count; i++)
{
var hash = Entries[i].HashCode;
if (hashCode < 0) continue;
var bucket = hash % Buckets.Length;
Entries[i].Next = Buckets[bucket];
Buckets[bucket] = i;
}
}
// 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 };
Buckets[targetBucket] = Count++;
}
#endregion
#region Nested Types
[DebuggerDisplay("Type='{Key}' Registrations='{Count}'")]
public struct Entry
{
public int HashCode;
public int Next;
public Type Key;
public int Count;
public int[] Data;
}
#endregion
}
}

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

@ -7,7 +7,6 @@ using Unity.Utility;
namespace Unity.Storage namespace Unity.Storage
{ {
[SecuritySafeCritical]
[DebuggerDisplay("Registrations ({Count}) ")] [DebuggerDisplay("Registrations ({Count}) ")]
internal class Registrations : IRegistry<Type, IRegistry<string, IPolicySet>> internal class Registrations : IRegistry<Type, IRegistry<string, IPolicySet>>
{ {
@ -32,23 +31,11 @@ namespace Unity.Storage
public Registrations(int capacity) public Registrations(int capacity)
{ {
var size = HashHelpers.GetPrime(capacity); var size = HashHelpers.GetPrime(capacity);
Buckets = new int[size]; Buckets = new int[size];
Entries = new Entry[size]; Entries = new Entry[size];
#if !NET40 HashHelpers.FillArray(Buckets, -1);
unsafe
{
fixed (int* bucketsPtr = Buckets)
{
int* ptr = bucketsPtr;
var end = bucketsPtr + Buckets.Length;
while (ptr < end) *ptr++ = -1;
}
}
#else
for(int i = 0; i < Buckets.Length; i++)
Buckets[i] = -1;
#endif
} }
public Registrations(int capacity, LinkedNode<Type, IRegistry<string, IPolicySet>> head) public Registrations(int capacity, LinkedNode<Type, IRegistry<string, IPolicySet>> head)

67
src/Storage/Registry.cs Normal file
Просмотреть файл

@ -0,0 +1,67 @@
using System;
using Unity.Policy;
using Unity.Resolution;
using Unity.Utility;
namespace Unity.Storage
{
public class Registry
{
#region Fields
public readonly int[] Buckets;
public readonly Entry[] Entries;
public int Count;
#endregion
#region Constructors
public Registry(int capacity = 37)
{
var size = HashHelpers.GetPrime(capacity);
Buckets = new int[size];
Entries = new Entry[size];
HashHelpers.FillArray(Buckets, -1);
}
public Registry(Registry registry)
: this(HashHelpers.GetPrime(registry.Entries.Length * 2))
{
Array.Copy(registry.Entries, 0, Entries, 0, registry.Count);
for (var i = 0; i < registry.Count; i++)
{
var hashCode = Entries[i].HashCode;
if (hashCode < 0) continue;
var bucket = hashCode % Buckets.Length;
Entries[i].Next = Buckets[bucket];
Buckets[bucket] = i;
}
Count = registry.Count;
registry.Count = 0;
}
#endregion
public bool RequireToGrow => (Entries.Length - Count) < 100 &&
(float)Count / Entries.Length > 0.72f;
#region Nested Types
public struct Entry
{
public int HashCode;
public NamedType Key;
public int Next;
public IPolicySet Reference;
}
#endregion
}
}

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

@ -28,38 +28,13 @@ namespace Unity.Strategies
{ {
LifetimeManager policy = null; LifetimeManager policy = null;
if (context.Registration is ContainerRegistration registration) if (context.Registration is InternalRegistration registration)
policy = registration.LifetimeManager; policy = registration.LifetimeManager;
if (null == policy || policy is PerResolveLifetimeManager) if (null == policy || policy is PerResolveLifetimeManager)
policy = (LifetimeManager)context.Get(typeof(LifetimeManager)); policy = (LifetimeManager)context.Get(typeof(LifetimeManager));
if (null == policy)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
if (!context.RegistrationType.GetTypeInfo().IsGenericType) return;
#else
if (!context.RegistrationType.IsGenericType) return;
#endif
var manager = (LifetimeManager)context.Get(context.Type.GetGenericTypeDefinition(),
context.Name, typeof(LifetimeManager));
if (null == manager) return;
lock (_genericLifetimeManagerLock) if (null == policy) return;
{
// check whether the policy for closed-generic has been added since first checked
policy = (LifetimeManager)context.Registration.Get(typeof(LifetimeManager));
if (null == policy)
{
policy = manager.CreateLifetimePolicy();
context.Registration.Set(typeof(LifetimeManager), policy);
if (policy is IDisposable)
{
context.Lifetime.Add(policy);
}
}
}
}
if (policy is SynchronizedLifetimeManager recoveryPolicy) if (policy is SynchronizedLifetimeManager recoveryPolicy)
context.RequiresRecovery = recoveryPolicy; context.RequiresRecovery = recoveryPolicy;
@ -76,7 +51,7 @@ namespace Unity.Strategies
{ {
LifetimeManager policy = null; LifetimeManager policy = null;
if (context.Registration is ContainerRegistration registration) if (context.Registration is InternalRegistration registration)
policy = registration.LifetimeManager; policy = registration.LifetimeManager;
if (null == policy || policy is PerResolveLifetimeManager) if (null == policy || policy is PerResolveLifetimeManager)
@ -92,7 +67,7 @@ namespace Unity.Strategies
public override bool RequiredToBuildType(IUnityContainer container, Type type, InternalRegistration registration, params InjectionMember[] injectionMembers) public override bool RequiredToBuildType(IUnityContainer container, Type type, InternalRegistration registration, params InjectionMember[] injectionMembers)
{ {
var policy = registration.Get(typeof(LifetimeManager)); var policy = registration.LifetimeManager;
if (null != policy) if (null != policy)
{ {
return policy is TransientLifetimeManager ? false : true; return policy is TransientLifetimeManager ? false : true;

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

@ -45,7 +45,7 @@ namespace Unity
var registration = new ContainerRegistration(_validators, typeTo, (LifetimeManager)lifetimeManager, injectionMembers); var registration = new ContainerRegistration(_validators, typeTo, (LifetimeManager)lifetimeManager, injectionMembers);
// Add or replace existing // Add or replace existing
var previous = container.Register(registeredType, name, registration); var previous = container.RegisterLegacy(registeredType, name, registration);
if (previous is ContainerRegistration old && if (previous is ContainerRegistration old &&
old.LifetimeManager is IDisposable disposable) old.LifetimeManager is IDisposable disposable)
{ {
@ -125,7 +125,7 @@ namespace Unity
var registration = new ContainerRegistration(null, mappedToType, ((LifetimeManager)lifetimeManager)); var registration = new ContainerRegistration(null, mappedToType, ((LifetimeManager)lifetimeManager));
// Add or replace existing // Add or replace existing
var previous = container.Register(typeFrom, name, registration); var previous = container.RegisterLegacy(typeFrom, name, registration);
if (previous is ContainerRegistration old && if (previous is ContainerRegistration old &&
old.LifetimeManager is IDisposable disposable) old.LifetimeManager is IDisposable disposable)
{ {
@ -183,7 +183,7 @@ namespace Unity
var registration = new ContainerRegistration(_validators, type, ((LifetimeManager)lifetimeManager), injectionMembers); var registration = new ContainerRegistration(_validators, type, ((LifetimeManager)lifetimeManager), injectionMembers);
// Add or replace existing // Add or replace existing
var previous = container.Register(type, name, registration); var previous = container.RegisterLegacy(type, name, registration);
if (previous is ContainerRegistration old && if (previous is ContainerRegistration old &&
old.LifetimeManager is IDisposable disposable) old.LifetimeManager is IDisposable disposable)
{ {

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

@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Unity.Injection;
using Unity.Lifetime;
using Unity.Registration;
using Unity.Resolution;
namespace Unity
{
public partial class UnityContainer : IUnityContainerAsync
{
#region Registration
#region Type
/// <inheritdoc />
IUnityContainer IUnityContainerAsync.RegisterType(IEnumerable<Type> interfaces, Type type, string name, ITypeLifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
{
throw new NotImplementedException();
}
#endregion
#region Factory
/// <inheritdoc />
IUnityContainer IUnityContainerAsync.RegisterFactory(IEnumerable<Type> interfaces, string name, Func<IUnityContainer, Type, string, object> factory, IFactoryLifetimeManager lifetimeManager)
{
// Validate input
// TODO: Move to diagnostic
if (null == interfaces) throw new ArgumentNullException(nameof(interfaces));
if (null == factory) throw new ArgumentNullException(nameof(factory));
if (null == lifetimeManager) lifetimeManager = TransientLifetimeManager.Instance;
if (((LifetimeManager)lifetimeManager).InUse) throw new InvalidOperationException(LifetimeManagerInUse);
// Create registration and add to appropriate storage
var container = lifetimeManager is SingletonLifetimeManager ? _root : this;
// TODO: InjectionFactory
#pragma warning disable CS0618
var injectionFactory = new InjectionFactory(factory);
#pragma warning restore CS0618
var injectionMembers = new InjectionMember[] { injectionFactory };
var registration = new ContainerRegistration(_validators, (LifetimeManager)lifetimeManager, injectionMembers);
// Add Injection Members
//injectionFactory.AddPolicies<BuilderContext, ContainerRegistration>(
// type, type, name, ref registration);
// Register interfaces
var replaced = container.AddOrReplaceRegistrations(interfaces, name, registration)
.ToArray();
// Release replaced registrations
if (0 != replaced.Length)
{
Task.Factory.StartNew(() =>
{
foreach (InternalRegistration previous in replaced)
{
if (0 == previous.Release() && previous.LifetimeManager is IDisposable disposable)
{
// Dispose replaced lifetime manager
container.LifetimeContainer.Remove(disposable);
disposable.Dispose();
}
}
});
}
return this;
}
#endregion
#region Instance
/// <inheritdoc />
IUnityContainer IUnityContainerAsync.RegisterInstance(IEnumerable<Type> interfaces, string name, object instance, IInstanceLifetimeManager lifetimeManager)
{
// Validate input
// TODO: Move to diagnostic
if (null == interfaces && null == instance) throw new ArgumentNullException(nameof(interfaces));
// Validate lifetime manager
if (null == lifetimeManager) lifetimeManager = new ContainerControlledLifetimeManager();
if (((LifetimeManager)lifetimeManager).InUse) throw new InvalidOperationException(LifetimeManagerInUse);
((LifetimeManager)lifetimeManager).SetValue(instance, LifetimeContainer);
// Create registration and add to appropriate storage
var mappedToType = instance?.GetType();
var container = lifetimeManager is SingletonLifetimeManager ? _root : this;
var registration = new ContainerRegistration(mappedToType, (LifetimeManager)lifetimeManager);
// Register interfaces
var replaced = container.AddOrReplaceRegistrations(interfaces, name, registration)
.ToArray();
// Release replaced registrations
if (0 != replaced.Length)
{
Task.Factory.StartNew(() =>
{
foreach (InternalRegistration previous in replaced)
{
if (0 == previous.Release() && previous.LifetimeManager is IDisposable disposable)
{
// Dispose replaced lifetime manager
container.LifetimeContainer.Remove(disposable);
disposable.Dispose();
}
}
});
}
return this;
}
#endregion
#endregion
#region Registrations
/// <inheritdoc />
IEnumerable<IContainerRegistration> IUnityContainerAsync.Registrations
{
get
{
throw new NotImplementedException();
}
}
/// <inheritdoc />
bool IUnityContainerAsync.IsRegistered(Type type, string name)
{
throw new NotImplementedException();
}
#endregion
#region Hierarchy
/// <inheritdoc />
IUnityContainer IUnityContainerAsync.Parent => throw new NotImplementedException();
/// <inheritdoc />
IUnityContainer IUnityContainerAsync.CreateChildContainer()
{
throw new NotImplementedException();
}
#endregion
#region Resolution
/// <inheritdoc />
Task<object> IUnityContainerAsync.Resolve(Type type, string name, params ResolverOverride[] overrides)
{
return null;// _getPipeline(type, name).Invoke(this, overrides);
}
#endregion
}
}

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

@ -58,7 +58,7 @@ namespace Unity
internal Func<Type, string, IPolicySet> GetRegistration; internal Func<Type, string, IPolicySet> GetRegistration;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal Func<Type, string, InternalRegistration, IPolicySet> Register; internal Func<Type, string, InternalRegistration, IPolicySet> RegisterLegacy;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] [DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal GetPolicyDelegate GetPolicy; internal GetPolicyDelegate GetPolicy;
@ -98,6 +98,8 @@ namespace Unity
_root = _parent._root; _root = _parent._root;
SetDefaultPolicies = parent.SetDefaultPolicies; SetDefaultPolicies = parent.SetDefaultPolicies;
// Registry
// Methods // Methods
_get = _parent._get; _get = _parent._get;
_getGenericRegistration = _parent._getGenericRegistration; _getGenericRegistration = _parent._getGenericRegistration;
@ -105,7 +107,7 @@ namespace Unity
IsTypeExplicitlyRegistered = _parent.IsTypeExplicitlyRegistered; IsTypeExplicitlyRegistered = _parent.IsTypeExplicitlyRegistered;
GetRegistration = _parent.GetRegistration; GetRegistration = _parent.GetRegistration;
Register = CreateAndSetOrUpdate; RegisterLegacy = CreateAndSetOrUpdate;
GetPolicy = parent.GetPolicy; GetPolicy = parent.GetPolicy;
SetPolicy = CreateAndSetPolicy; SetPolicy = CreateAndSetPolicy;
ClearPolicy = delegate { }; ClearPolicy = delegate { };
@ -242,7 +244,7 @@ namespace Unity
SetupChildContainerBehaviors(); SetupChildContainerBehaviors();
} }
return AddOrUpdate(type, name, registration); return AddOrUpdateLegacy(type, name, registration);
} }
private void SetupChildContainerBehaviors() private void SetupChildContainerBehaviors()
@ -254,7 +256,7 @@ namespace Unity
_registrations = new Registrations(ContainerInitialCapacity); _registrations = new Registrations(ContainerInitialCapacity);
Set(null, null, Defaults); Set(null, null, Defaults);
Register = AddOrUpdate; RegisterLegacy = AddOrUpdateLegacy;
GetPolicy = Get; GetPolicy = Get;
SetPolicy = Set; SetPolicy = Set;
ClearPolicy = Clear; ClearPolicy = Clear;

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

@ -32,6 +32,9 @@ namespace Unity
// Context // Context
_context = new ContainerContext(this); _context = new ContainerContext(this);
// Registry
Register = InitAndAdd;
// Methods // Methods
_get = Get; _get = Get;
_getGenericRegistration = GetOrAddGeneric; _getGenericRegistration = GetOrAddGeneric;
@ -39,7 +42,7 @@ namespace Unity
IsTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally; IsTypeExplicitlyRegistered = IsTypeTypeExplicitlyRegisteredLocally;
GetRegistration = GetOrAdd; GetRegistration = GetOrAdd;
Register = AddOrUpdate; RegisterLegacy = AddOrUpdateLegacy;
GetPolicy = Get; GetPolicy = Get;
SetPolicy = Set; SetPolicy = Set;
ClearPolicy = Clear; ClearPolicy = Clear;
@ -78,6 +81,7 @@ namespace Unity
// Register this instance // Register this instance
((IUnityContainer)this).RegisterInstance(typeof(IUnityContainer), null, this, new ContainerLifetimeManager()); ((IUnityContainer)this).RegisterInstance(typeof(IUnityContainer), null, this, new ContainerLifetimeManager());
((IUnityContainerAsync)this).RegisterInstance(new[] { typeof(IUnityContainer) }, null, this, new ContainerLifetimeManager());
} }
#endregion #endregion

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

@ -1,9 +1,11 @@
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using Unity.Policy; using Unity.Policy;
using Unity.Registration; using Unity.Registration;
using Unity.Resolution;
using Unity.Storage; using Unity.Storage;
namespace Unity namespace Unity
@ -19,8 +21,19 @@ namespace Unity
#endregion #endregion
#region Delegates
private delegate IPolicySet RegisterDelegate(ref NamedType key, InternalRegistration registration);
#endregion
#region Registration Fields #region Registration Fields
// Register single type
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private RegisterDelegate Register;
internal IPolicySet Defaults; internal IPolicySet Defaults;
private readonly object _syncRoot = new object(); private readonly object _syncRoot = new object();
private LinkedNode<Type, object> _validators; private LinkedNode<Type, object> _validators;
@ -339,9 +352,112 @@ namespace Unity
#endregion #endregion
#region Dynamic Registrations
private IPolicySet GetDynamicRegistration(Type type, string name)
{
var registration = _get(type, name);
if (null != registration) return registration;
var info = type.GetTypeInfo();
return !info.IsGenericType
? _root.GetOrAdd(type, name)
: GetOrAddGeneric(type, name, info.GetGenericTypeDefinition());
}
private IPolicySet CreateRegistration(Type type, string name)
{
var registration = new InternalRegistration(type, name);
if (type.GetTypeInfo().IsGenericType)
{
var factory = (InternalRegistration)_get(type.GetGenericTypeDefinition(), 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(type, registration);
return registration;
}
private IPolicySet CreateRegistration(Type type, Type policyInterface, object policy)
{
var registration = new InternalRegistration(policyInterface, policy);
registration.BuildChain = GetBuilders(type, registration);
return registration;
}
#endregion
#region Registration manipulation #region Registration manipulation
private IPolicySet AddOrUpdate(Type type, string name, InternalRegistration registration) private IEnumerable<IPolicySet> AddOrReplaceRegistrations(IEnumerable<Type> interfaces, string name, ContainerRegistration registration)
{
NamedType key;
int count = 0;
key.Name = name;
if (null != interfaces)
{
foreach (var type in interfaces)
{
// Type to register
key.Type = type;
// 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;
}
count++;
}
}
if (0 == count)
{
// TODO: Move to diagnostic
if (null == registration.Type) throw new ArgumentNullException(nameof(interfaces));
// Type to register
key.Type = registration.Type;
// 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;
}
}
}
private IPolicySet AddOrUpdateLegacy(Type type, string name, InternalRegistration registration)
{ {
var collisions = 0; var collisions = 0;
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF; var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;

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

@ -0,0 +1,83 @@
using Unity.Policy;
using Unity.Registration;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
#region Fields
private Registry _registry;
private Metadata _metadata;
#endregion
#region
private IPolicySet InitAndAdd(ref NamedType key, InternalRegistration registration)
{
lock (_syncRoot)
{
if (Register == InitAndAdd)
{
_registry = new Registry();
_metadata = new Metadata();
Register = AddOrReplace;
}
}
return Register(ref key, registration);
}
private IPolicySet AddOrReplace(ref NamedType key, InternalRegistration registration)
{
var hashCode = key.GetHashCode();
var targetBucket = hashCode % _registry.Buckets.Length;
var collisions = 0;
lock (_syncRoot)
{
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;
}
var existing = candidate.Reference;
candidate.Reference = registration;
return existing;
}
if (_registry.RequireToGrow || ListToHashCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = hashCode % _registry.Buckets.Length;
}
ref var entry = ref _registry.Entries[_registry.Count];
entry.HashCode = hashCode;
entry.Next = _registry.Buckets[targetBucket];
entry.Key = key;
entry.Reference = registration;
var position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
_metadata.Add(key.Type, position);
return null;
}
}
#endregion
}
}

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

@ -26,48 +26,6 @@ namespace Unity
[SecuritySafeCritical] [SecuritySafeCritical]
public partial class UnityContainer public partial class UnityContainer
{ {
#region Dynamic Registrations
private IPolicySet GetDynamicRegistration(Type type, string name)
{
var registration = _get(type, name);
if (null != registration) return registration;
var info = type.GetTypeInfo();
return !info.IsGenericType
? _root.GetOrAdd(type, name)
: GetOrAddGeneric(type, name, info.GetGenericTypeDefinition());
}
private IPolicySet CreateRegistration(Type type, string name)
{
var registration = new InternalRegistration(type, name);
if (type.GetTypeInfo().IsGenericType)
{
var factory = (InternalRegistration)_get(type.GetGenericTypeDefinition(), name);
if (null != factory)
{
registration.InjectionMembers = factory.InjectionMembers;
registration.Map = factory.Map;
}
}
registration.BuildChain = GetBuilders(type, registration);
return registration;
}
private IPolicySet CreateRegistration(Type type, Type policyInterface, object policy)
{
var registration = new InternalRegistration(policyInterface, policy);
registration.BuildChain = GetBuilders(type, registration);
return registration;
}
#endregion
#region Resolving Collections #region Resolving Collections
internal static object ResolveEnumerable<TElement>(ref BuilderContext context) internal static object ResolveEnumerable<TElement>(ref BuilderContext context)

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

@ -1,7 +1,9 @@
using System; using System;
using System.Security;
namespace Unity.Utility namespace Unity.Utility
{ {
[SecuritySafeCritical]
internal static class HashHelpers internal static class HashHelpers
{ {
// Table of prime numbers to use as hash table sizes. // Table of prime numbers to use as hash table sizes.
@ -74,5 +76,24 @@ namespace Unity.Utility
// This is the maximum prime smaller than Array.MaxArrayLength // This is the maximum prime smaller than Array.MaxArrayLength
public const int MaxPrimeArrayLength = 0x7FEFFFFD; public const int MaxPrimeArrayLength = 0x7FEFFFFD;
public static void FillArray(int[] array, int value)
{
#if !NET40
unsafe
{
fixed (int* bucketsPtr = array)
{
int* ptr = bucketsPtr;
var end = bucketsPtr + array.Length;
while (ptr < end) *ptr++ = value;
}
}
#else
for(int i = 0; i < array.Length; i++)
array[i] = value;
#endif
}
} }
} }

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

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<IsPackable>false</IsPackable>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\src\package.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\SpecificationTests\diagnostic\Unity.Specification.Diagnostic.csproj" />
<ProjectReference Include="..\..\src\Unity.Container.csproj" />
</ItemGroup>
</Project>

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

@ -0,0 +1,32 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
namespace Registration
{
[TestClass]
public class Type : Unity.Specification.Async.Registration.Types.SpecificationTests
{
public override IUnityContainerAsync GetContainer()
{
return new UnityContainer();
}
}
[TestClass]
public class Factory : Unity.Specification.Async.Registration.Factory.SpecificationTests
{
public override IUnityContainerAsync GetContainer()
{
return new UnityContainer();
}
}
[TestClass]
public class Instance : Unity.Specification.Async.Registration.Instance.SpecificationTests
{
public override IUnityContainerAsync GetContainer()
{
return new UnityContainer();
}
}
}

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

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<IsPackable>false</IsPackable>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\src\package.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\SpecificationTestsAsync\src\Unity.Specification.Async.csproj" />
<ProjectReference Include="..\..\src\Unity.Container.csproj" />
</ItemGroup>
</Project>