Changing registrations engine
This commit is contained in:
Родитель
ec39834140
Коммит
9ad7e68bee
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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>
|
Загрузка…
Ссылка в новой задаче