This commit is contained in:
Eugene Sadovoi 2019-06-07 19:57:09 -04:00
Родитель 7c0a0afa69
Коммит 55e5eff24f
37 изменённых файлов: 1034 добавлений и 662 удалений

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

@ -80,7 +80,7 @@ namespace Unity.Builder
if (LifetimeManager.NoValue != value) return value;
}
return Resolve(pipeline);
return Resolve(type, name, pipeline);
}
#endregion
@ -90,7 +90,7 @@ namespace Unity.Builder
public object? Get(Type policyInterface)
{
return List?.Get(Type, Name, policyInterface) ??
return List?.Get(Type, Name, policyInterface) ??
Registration?.Get(policyInterface);
}
@ -381,7 +381,7 @@ namespace Unity.Builder
if (LifetimeManager.NoValue != value) return value;
}
return Resolve(pipeline);
return Resolve(type, null, pipeline);
}
public object? Resolve(Type type, IRegistration registration)
@ -391,8 +391,8 @@ namespace Unity.Builder
unsafe
{
var thisContext = this;
var container = registration.LifetimeManager is ContainerControlledLifetimeManager containerControlled
? (ContainerContext)containerControlled.Scope
var container = registration.LifetimeManager is ContainerControlledLifetimeManager containerControlled
? (ContainerContext)containerControlled.Scope
: ContainerContext;
var context = new BuilderContext
@ -411,10 +411,10 @@ namespace Unity.Builder
var manager = registration.LifetimeManager switch
{
null => TransientLifetimeManager.Instance,
PerResolveLifetimeManager _ => (LifetimeManager?)context.Get(typeof(LifetimeManager)) ??
null => TransientLifetimeManager.Instance,
PerResolveLifetimeManager _ => (LifetimeManager?)context.Get(typeof(LifetimeManager)) ??
TransientLifetimeManager.Instance,
_ => registration.LifetimeManager
_ => registration.LifetimeManager
};
// Check if already got value
@ -441,26 +441,36 @@ namespace Unity.Builder
}
}
public object? Resolve(ResolveDelegate<BuilderContext> pipeline)
public object? Resolve(Type type, string? name, ResolveDelegate<BuilderContext> pipeline)
{
// Setup Context
var synchronized = pipeline.Target as SynchronizedLifetimeManager;
var thisContext = this;
try
unsafe
{
// Execute pipeline
var value = pipeline(ref thisContext);
(pipeline.Target as LifetimeManager)?.Set(value, ContainerContext.Lifetime);
// Setup Context
var context = new BuilderContext
{
ContainerContext = pipeline.Target is ContainerControlledLifetimeManager containerControlled
? (ContainerContext)containerControlled.Scope
: ContainerContext,
IsAsync = IsAsync,
List = List,
Type = type,
Name = name,
Overrides = Overrides,
DeclaringType = Type,
#if !NET40
Parent = new IntPtr(Unsafe.AsPointer(ref thisContext))
#endif
};
var manager = pipeline.Target as LifetimeManager;
var value = pipeline(ref context);
manager?.SetValue(value, ContainerContext.Lifetime);
return value;
}
catch when (null != synchronized)
{
synchronized.Recover();
throw;
}
}
#endregion
#endregion
}
}
}

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

@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Unity.Builder;
@ -12,7 +13,7 @@ namespace Unity.Factories
private static readonly MethodInfo EnumerableMethod =
typeof(EnumerableResolver).GetTypeInfo()
.GetDeclaredMethod(nameof(EnumerableResolver.Resolver));
.GetDeclaredMethod(nameof(EnumerableResolver.EnumerableHandler));
private static readonly MethodInfo EnumerableFactory =
typeof(EnumerableResolver).GetTypeInfo()
@ -29,6 +30,7 @@ namespace Unity.Factories
var typeArgument = type.GetTypeInfo().GenericTypeArguments.First();
if (typeArgument.GetTypeInfo().IsGenericType)
#else
Debug.Assert(0 < type.GenericTypeArguments.Length);
var typeArgument = type.GenericTypeArguments.First();
if (typeArgument.IsGenericType)
#endif
@ -50,7 +52,7 @@ namespace Unity.Factories
#region Implementation
private static object Resolver<TElement>(ref BuilderContext context)
private static object EnumerableHandler<TElement>(ref BuilderContext context)
{
return ((UnityContainer)context.Container).ResolveEnumerable<TElement>(context.Resolve,
context.Name);

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

@ -46,7 +46,7 @@ namespace Unity.Factories
var lifetime = context.Get(typeof(LifetimeManager));
if (lifetime is PerResolveLifetimeManager)
{
var perBuildLifetime = new InternalPerResolveLifetimeManager(context.Existing);
var perBuildLifetime = new RuntimePerResolveLifetimeManager(context.Existing);
context.Set(typeof(LifetimeManager), perBuildLifetime);
}

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

@ -0,0 +1,23 @@
using System;
using System.Diagnostics;
namespace Unity.Lifetime
{
internal class ContainerLifetimeManager : LifetimeManager
{
protected override LifetimeManager OnCreateLifetimeManager()
=> throw new NotImplementedException();
public override object GetValue(ILifetimeContainer container)
{
Debug.Assert(null != container);
return container.Container;
}
public override object TryGetValue(ILifetimeContainer container)
{
Debug.Assert(null != container);
return container.Container;
}
}
}

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

@ -7,7 +7,7 @@ namespace Unity.Lifetime
/// but also provides a signal to the default build plan, marking the type so that
/// instances are reused across the build up object graph.
/// </summary>
internal class InternalPerResolveLifetimeManager : PerResolveLifetimeManager
internal class RuntimePerResolveLifetimeManager : PerResolveLifetimeManager
{
/// <summary>
/// Construct a new <see cref="PerResolveLifetimeManager"/> object that stores the
@ -17,7 +17,7 @@ namespace Unity.Lifetime
/// normal <see cref="LifetimeManager.SetValue"/> method is not used here.
/// </summary>
/// <param name="value">InjectionParameterValue to store.</param>
public InternalPerResolveLifetimeManager(object? value)
public RuntimePerResolveLifetimeManager(object? value)
{
base.value = value;
InUse = true;

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

@ -417,7 +417,7 @@ namespace Unity
}
context.Set(typeof(LifetimeManager),
new InternalPerResolveLifetimeManager(context.Existing));
new RuntimePerResolveLifetimeManager(context.Existing));
}
return null == pipeline ? context.Existing : pipeline.Invoke(ref context);

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

@ -11,7 +11,7 @@ namespace Unity
{
#region Fields
private static readonly ConstructorInfo PerResolveInfo = typeof(InternalPerResolveLifetimeManager)
private static readonly ConstructorInfo PerResolveInfo = typeof(RuntimePerResolveLifetimeManager)
.GetTypeInfo().DeclaredConstructors.First();
protected static readonly Expression SetPerBuildSingletonExpr =

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

@ -122,7 +122,7 @@ namespace Unity
context.Existing = info.Invoke(dependencies);
context.Set(typeof(LifetimeManager),
new InternalPerResolveLifetimeManager(context.Existing));
new RuntimePerResolveLifetimeManager(context.Existing));
}
return null == pipeline ? context.Existing : pipeline.Invoke(ref context);

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

@ -43,51 +43,26 @@ namespace Unity
// Try finding factory
TypeFactoryDelegate? factory = builder.Policies?.Get<TypeFactoryDelegate>();
if (builder.Policies is ExplicitRegistration @explicit)
{
#if NETCOREAPP1_0 || NETSTANDARD1_0
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
#else
if (null != builder.Type && builder.Type.IsGenericType)
if (null != builder.Type && builder.Type.IsGenericType)
#endif
{
factory = (TypeFactoryDelegate?)builder.ContainerContext.Get(builder.Type.GetGenericTypeDefinition(),
typeof(TypeFactoryDelegate));
}
else if (null != builder.Type && builder.Type.IsArray)
{
if (builder.Type.GetArrayRank() == 1)
{
var resolve = ArrayResolver.Factory(builder.Type, builder.ContainerContext.Container);
return builder.Pipeline((ref BuilderContext context) => resolve(ref context));
}
else
{
var message = $"Invalid array {builder.Type}. Only arrays of rank 1 are supported";
return (ref BuilderContext context) => throw new InvalidRegistrationException(message);
}
}
{
factory = (TypeFactoryDelegate?)builder.ContainerContext.Get(builder.Type.GetGenericTypeDefinition(),
typeof(TypeFactoryDelegate));
}
else if(builder.Policies is ImplicitRegistration @implicit)
else if (null != builder.Type && builder.Type.IsArray)
{
#if NETCOREAPP1_0 || NETSTANDARD1_0
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
#else
if (null != builder.Type && builder.Type.IsGenericType)
#endif
if (builder.Type.GetArrayRank() == 1)
{
factory = (TypeFactoryDelegate?)builder.ContainerContext.Get(builder.Type.GetGenericTypeDefinition(),
typeof(TypeFactoryDelegate));
var resolve = ArrayResolver.Factory(builder.Type, builder.ContainerContext.Container);
return builder.Pipeline((ref BuilderContext context) => resolve(ref context));
}
else if (builder.Type?.IsArray ?? false)
else
{
if (builder.Type?.GetArrayRank() == 1)
return builder.Pipeline(ArrayResolver.Factory(builder.Type, builder.ContainerContext.Container));
else
{
var message = $"Invalid array {builder.Type}. Only arrays of rank 1 are supported";
return (ref BuilderContext context) => throw new InvalidRegistrationException(message);
}
var message = $"Invalid array {builder.Type}. Only arrays of rank 1 are supported";
return (ref BuilderContext context) => throw new InvalidRegistrationException(message);
}
}

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

@ -2,7 +2,6 @@
using Unity.Builder;
using Unity.Lifetime;
using Unity.Resolution;
using static Unity.UnityContainer;
namespace Unity
{
@ -12,31 +11,24 @@ namespace Unity
public override ResolveDelegate<BuilderContext>? Build(ref PipelineBuilder builder)
{
if (builder.LifetimeManager is ContainerControlledLifetimeManager manager)
ResolveDelegate<BuilderContext>? pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
return builder.LifetimeManager is SynchronizedLifetimeManager manager ?
(ref BuilderContext context) =>
{
var pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
return (ref BuilderContext context) =>
try
{
var scope = context.ContainerContext;
try
{
// Switch context to lifetime's scope
context.ContainerContext = (ContainerContext)manager.Scope;
// Build withing the scope
return pipeline(ref context);
}
finally
{
context.ContainerContext = scope;
}
};
// Build withing the scope
return pipeline(ref context);
}
catch
{
manager.Recover();
throw;
}
}
return builder.Pipeline(); ;
: pipeline;
}
#endregion

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

@ -19,6 +19,7 @@ namespace Unity.Registration
{
Next = null;
Type = type;
LifetimeManager = new TransientLifetimeManager();
InjectionMembers = null;
BuildRequired = false;
}
@ -40,7 +41,7 @@ namespace Unity.Registration
: base(owner, name)
{
Type = type;
LifetimeManager = lifetimeManager is TransientLifetimeManager ? null : lifetimeManager;
LifetimeManager = lifetimeManager;
Next = owner.Defaults;
InjectionMembers = null != injectionMembers && 0 < injectionMembers.Length ? injectionMembers : null;
BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired) || lifetimeManager is PerResolveLifetimeManager;

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

@ -15,7 +15,7 @@ namespace Unity.Registration
if (manager is IDisposable managerDisposable)
owner.Context.Lifetime.Add(managerDisposable);
LifetimeManager = manager is TransientLifetimeManager ? null : manager;
LifetimeManager = manager;
// Factory resolver
if (manager is PerResolveLifetimeManager)
@ -23,7 +23,7 @@ namespace Unity.Registration
Pipeline = (ref BuilderContext context) =>
{
var value = factory(context.Container, context.Type, context.Name);
context.Set(typeof(LifetimeManager), new InternalPerResolveLifetimeManager(value));
context.Set(typeof(LifetimeManager), new RuntimePerResolveLifetimeManager(value));
return value;
};
}

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

@ -19,11 +19,6 @@ namespace Unity.Registration
manager.InUse = true;
manager.SetValue(instance, owner.Context.Lifetime);
Pipeline = (ref BuilderContext context) => throw new InvalidOperationException("Instance value no longer available");
//Pipeline = manager switch
//{
// ExternallyControlledLifetimeManager _ => ExternalLifetime,
// _ => (ResolveDelegate<BuilderContext>)OtherLifetime
//};
LifetimeManager = manager;
}

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

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

@ -28,7 +28,7 @@
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' != '' AND '$(TargetFramework)' != 'netstandard1.0' ">
<Compile Remove="Utility\ConcurrentDictionary.cs" />
<Compile Remove="UnityContainer\Utility\ConcurrentDictionary.cs" />
</ItemGroup>
<PropertyGroup>

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

@ -1,514 +0,0 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Registration;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
#region Get Pipeline
private ResolveDelegate<BuilderContext>? TryGetPipeline(ref HashKey key)
{
// Iterate through containers hierarchy
for (UnityContainer? container = this; null != container; container = container._parent)
{
// Skip to parent if no registrations
if (null == container._metadata) continue;
Debug.Assert(null != container._registry);
var registry = container._registry;
// Check for exact match
for (var i = registry.Buckets[key.HashCode % registry.Buckets.Length]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != key) continue;
// Found it
return candidate.Pipeline;
}
}
return null;
}
internal ResolveDelegate<BuilderContext> GetPipeline(ref HashKey key)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var info = key.Type?.GetTypeInfo();
return null != info && info.IsGenericType
? GenericGetPipeline(ref key, info)
: GetNonGenericPipeline(ref key);
#else
return null != key.Type && key.Type.IsGenericType
? GenericGetPipeline(ref key)
: GetNonGenericPipeline(ref key);
#endif
}
#endregion
#region Implementation
private ResolveDelegate<BuilderContext> GetNonGenericPipeline(ref HashKey key)
{
// Iterate through containers hierarchy
for (UnityContainer? container = this; null != container; container = container._parent)
{
// Skip to parent if no registrations
if (null == container._metadata) continue;
Debug.Assert(null != container._registry);
var registry = container._registry;
// Check for exact match
for (var i = registry.Buckets[key.HashCode % registry.Buckets.Length]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != key) continue;
// Found it
Debug.Assert(null != candidate.Pipeline);
return candidate.Pipeline;
}
}
Debug.Assert(null != _root);
return _root.PipelineFromType(ref key);
}
#if NETSTANDARD1_0 || NETCOREAPP1_0
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey key, TypeInfo info)
{
Debug.Assert(null != info);
#else
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey key)
{
#endif
Debug.Assert(null != key.Type);
int targetBucket;
bool initGenerics = true;
var keyGeneric = new HashKey();
var keyDefault = new HashKey();
Type type = key.Type;
Type? generic = null;
var name = key.Name;
// Iterate through containers hierarchy
for (UnityContainer? container = this; null != container; container = container._parent)
{
// Skip to parent if no registrations
if (null == container._metadata) continue;
Debug.Assert(null != container._registry);
var registry = container._registry;
// Exact match
targetBucket = key.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != key) continue;
Debug.Assert(null != candidate.Pipeline);
// Found a registration
return candidate.Pipeline;
}
// Generic registrations
if (initGenerics)
{
initGenerics = false;
#if NETSTANDARD1_0 || NETCOREAPP1_0
generic = info.GetGenericTypeDefinition();
#else
generic = type.GetGenericTypeDefinition();
#endif
keyGeneric = new HashKey(generic, name);
keyDefault = new HashKey(generic);
}
// Factory with the same name
targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != keyGeneric)
continue;
// Found a factory
return container.PipelineFromFactory(ref key, (ExplicitRegistration)candidate.Policies);
}
// Default factory
targetBucket = keyDefault.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != keyDefault)
continue;
// Found a factory
var typeFactory = (TypeFactoryDelegate)candidate.Policies.Get(typeof(TypeFactoryDelegate));
return container.PipelineFromTypeFactory(ref key, container, typeFactory);
}
}
Debug.Assert(null != _root);
return _root.PipelineFromType(ref key);
}
#endregion
#region Create Pipeline
private ResolveDelegate<BuilderContext> PipelineFromType(ref HashKey key)
{
Debug.Assert(null != key.Type);
Debug.Assert(null != _registry);
var type = key.Type;
var name = key.Name;
int count = -1;
var collisions = 0;
ResolveDelegate<BuilderContext>? pipeline = null;
lock (_syncLock)
{
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
ref var candidate = ref _registry.Entries[i];
if (candidate.Key != key)
{
collisions++;
continue;
}
if (null == candidate.Pipeline)
candidate.Pipeline = buildPipeline;
// Replaced registration
return candidate.Pipeline;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Next = _registry.Buckets[targetBucket];
entry.Type = type;
entry.IsExplicit = true;
entry.Pipeline = buildPipeline;
int position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
return buildPipeline;
object? buildPipeline(ref BuilderContext context)
{
// Wait for right moment
while (0 != Interlocked.Increment(ref count))
{
Interlocked.Decrement(ref count);
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
try
{
// Create if required
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, this, Context.TypePipelineCache);
pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
}
return pipeline(ref context);
}
finally
{
Interlocked.Decrement(ref count);
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromRegistration(ref HashKey key, ExplicitRegistration registration, int position)
{
Debug.Assert(null != _registry);
var type = key.Type;
var name = key.Name;
ResolveDelegate<BuilderContext>? pipeline = null;
if (null != registration.LifetimeManager && !(registration.LifetimeManager is TransientLifetimeManager))
{
registration.LifetimeManager.PipelineDelegate = (ResolveDelegate<BuilderContext>)BuildPipeline;
return registration.LifetimeManager.Pipeline;
}
return BuildPipeline;
object? BuildPipeline(ref BuilderContext context)
{
if (null != pipeline) return pipeline(ref context);
lock (registration)
{
if (null != pipeline) return pipeline(ref context);
PipelineBuilder builder = new PipelineBuilder(type, registration);
if (registration.LifetimeManager is LifetimeManager manager)
{
manager.PipelineDelegate = builder.Pipeline();
pipeline = manager.Pipeline;
}
else
pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
Debug.Assert(null != _registry);
lock (_syncLock)
{
if (ReferenceEquals(registration, _registry.Entries[position].Policies))
{
_registry.Entries[position].Pipeline = pipeline;
}
}
// Check if already created and acquire a lock if not
if (pipeline.Target is LifetimeManager lifetime)
{
// Make blocking check for result
var value = lifetime.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
}
return pipeline(ref context);
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromFactory(ref HashKey key, ExplicitRegistration factory)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
var type = key.Type;
var name = key.Name;
var owner = this;
int count = -1;
int position = 0;
var collisions = 0;
ResolveDelegate<BuilderContext>? pipeline = null;
ResolveDelegate<BuilderContext> buildPipeline;
var manager = null != factory.LifetimeManager && !(factory.LifetimeManager is TransientLifetimeManager)
? factory.LifetimeManager.CreateLifetimePolicy()
: null;
if (null != manager)
{
if (manager is IDisposable disposable) Context.Lifetime.Add(disposable);
if (manager is ContainerControlledLifetimeManager containerControlled) containerControlled.Scope = Context;
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)BuildPipeline;
buildPipeline = manager.Pipeline;
}
else
buildPipeline = BuildPipeline;
// Add Pipeline to the Registry
lock (_syncLock)
{
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
ref var candidate = ref _registry.Entries[i];
if (candidate.Key != key)
{
collisions++;
continue;
}
Debug.Assert(null != candidate.Pipeline);
// Has already been created
return candidate.Pipeline;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Type = type;
entry.Pipeline = buildPipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
// Return temporary pipeline
return buildPipeline;
// Create pipeline and add to Registry
object? BuildPipeline(ref BuilderContext context)
{
// Wait for right moment
while (0 != Interlocked.Increment(ref count))
{
Interlocked.Decrement(ref count);
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
try
{
// Create if required
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, owner);
pipeline = builder.Pipeline();
if (null != manager) manager.PipelineDelegate = pipeline;
Debug.Assert(null != pipeline);
}
var value = pipeline(ref context);
manager?.Set(value, LifetimeContainer);
return value;
}
finally
{
Interlocked.Decrement(ref count);
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromTypeFactory(ref HashKey key, UnityContainer container, TypeFactoryDelegate typeFactory)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
var type = key.Type;
var name = key.Name;
var owner = this;
int count = -1;
int position = 0;
var collisions = 0;
ResolveDelegate<BuilderContext>? pipeline = null;
// Add Pipeline to the Registry
lock (_syncLock)
{
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
ref var candidate = ref _registry.Entries[i];
if (candidate.Key != key)
{
collisions++;
continue;
}
Debug.Assert(null != candidate.Pipeline);
// Has already been created
return candidate.Pipeline;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Type = type;
entry.Pipeline = BuildPipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
// Return temporary pipeline
return BuildPipeline;
// Create pipeline and add to Registry
object? BuildPipeline(ref BuilderContext context)
{
// Wait for right moment
while (0 != Interlocked.Increment(ref count))
{
Interlocked.Decrement(ref count);
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
try
{
// Create if required
if (null == pipeline)
{
pipeline = typeFactory(type, container);
Debug.Assert(null != pipeline);
}
return pipeline(ref context);
}
finally
{
Interlocked.Decrement(ref count);
}
};
}
#endregion
}
}

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

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

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

@ -219,7 +219,6 @@ namespace Unity
}
// Setup Context
var synchronized = manager as SynchronizedLifetimeManager;
var context = new BuilderContext
{
List = new PolicyList(),
@ -237,17 +236,10 @@ namespace Unity
return value;
}
catch (Exception ex)
when (ex is InvalidRegistrationException || ex is CircularDependencyException || ex is ObjectDisposedException)
{
synchronized?.Recover();
if (ex is InvalidRegistrationException ||
ex is CircularDependencyException ||
ex is ObjectDisposedException)
{
var message = CreateErrorMessage(ex);
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
}
else throw;
var message = CreateErrorMessage(ex);
throw new ResolutionFailedException(context.Type, context.Name, message, ex);
}
}

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

@ -284,24 +284,5 @@ namespace Unity
}
#endregion
private class ContainerLifetimeManager : LifetimeManager
{
protected override LifetimeManager OnCreateLifetimeManager()
=> throw new NotImplementedException();
public override object GetValue(ILifetimeContainer container)
{
Debug.Assert(null != container);
return container.Container;
}
public override object TryGetValue(ILifetimeContainer container)
{
Debug.Assert(null != container);
return container.Container;
}
}
}
}

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

@ -0,0 +1,174 @@
using System;
using System.Diagnostics;
using System.Reflection;
using Unity.Builder;
using Unity.Registration;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
#region Get Pipeline
private ResolveDelegate<BuilderContext>? TryGetPipeline(ref HashKey key)
{
// Iterate through containers hierarchy
for (UnityContainer? container = this; null != container; container = container._parent)
{
// Skip to parent if no registrations
if (null == container._metadata) continue;
Debug.Assert(null != container._registry);
var registry = container._registry;
// Check for exact match
for (var i = registry.Buckets[key.HashCode % registry.Buckets.Length]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != key) continue;
// Found it
return candidate.Pipeline;
}
}
return null;
}
internal ResolveDelegate<BuilderContext> GetPipeline(ref HashKey key)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var info = key.Type?.GetTypeInfo();
return null != info && info.IsGenericType
? GenericGetPipeline(ref key, info)
: GetNonGenericPipeline(ref key);
#else
return null != key.Type && key.Type.IsGenericType
? GenericGetPipeline(ref key)
: GetNonGenericPipeline(ref key);
#endif
}
#endregion
#region Implementation
private ResolveDelegate<BuilderContext> GetNonGenericPipeline(ref HashKey key)
{
// Iterate through containers hierarchy
for (UnityContainer? container = this; null != container; container = container._parent)
{
// Skip to parent if no registrations
if (null == container._metadata) continue;
Debug.Assert(null != container._registry);
var registry = container._registry;
// Check for exact match
for (var i = registry.Buckets[key.HashCode % registry.Buckets.Length]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != key) continue;
// Found it
Debug.Assert(null != candidate.Pipeline);
return candidate.Pipeline;
}
}
Debug.Assert(null != _root);
return _root.PipelineFromUnregisteredType(ref key);
}
#if NETSTANDARD1_0 || NETCOREAPP1_0
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey key, TypeInfo info)
{
Debug.Assert(null != info);
#else
private ResolveDelegate<BuilderContext> GenericGetPipeline(ref HashKey key)
{
#endif
Debug.Assert(null != key.Type);
int targetBucket;
bool initGenerics = true;
var keyGeneric = new HashKey();
var keyDefault = new HashKey();
Type type = key.Type;
Type? generic = null;
var name = key.Name;
// Iterate through containers hierarchy
for (UnityContainer? container = this; null != container; container = container._parent)
{
// Skip to parent if no registrations
if (null == container._metadata) continue;
Debug.Assert(null != container._registry);
var registry = container._registry;
// Exact match
targetBucket = key.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != key) continue;
Debug.Assert(null != candidate.Pipeline);
// Found a registration
return candidate.Pipeline;
}
// Generic registrations
if (initGenerics)
{
initGenerics = false;
#if NETSTANDARD1_0 || NETCOREAPP1_0
generic = info.GetGenericTypeDefinition();
#else
generic = type.GetGenericTypeDefinition();
#endif
keyGeneric = new HashKey(generic, name);
keyDefault = new HashKey(generic);
}
// Factory with the same name
targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != keyGeneric)
continue;
// Found a factory
return container.PipelineFromOpenGeneric(ref key, (ExplicitRegistration)candidate.Policies);
}
// Default factory
targetBucket = keyDefault.HashCode % registry.Buckets.Length;
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
{
ref var candidate = ref registry.Entries[i];
if (candidate.Key != keyDefault)
continue;
// Found a factory
var typeFactory = (TypeFactoryDelegate)candidate.Policies.Get(typeof(TypeFactoryDelegate));
return container.PipelineFromTypeFactory(ref key, container, typeFactory);
}
}
Debug.Assert(null != _root);
return _root.PipelineFromUnregisteredType(ref key);
}
#endregion
}
}

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

@ -0,0 +1,119 @@
using System;
using System.Diagnostics;
using System.Threading;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Registration;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
private ResolveDelegate<BuilderContext> PipelineFromOpenGeneric(ref HashKey key, ExplicitRegistration factory)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
var type = key.Type;
var name = key.Name;
var owner = this;
int count = -1;
int position = 0;
var collisions = 0;
ResolveDelegate<BuilderContext>? pipeline = null;
ResolveDelegate<BuilderContext> buildPipeline;
var manager = null != factory.LifetimeManager && !(factory.LifetimeManager is TransientLifetimeManager)
? factory.LifetimeManager.CreateLifetimePolicy()
: null;
if (null != manager)
{
if (manager is IDisposable disposable) Context.Lifetime.Add(disposable);
if (manager is ContainerControlledLifetimeManager containerControlled) containerControlled.Scope = Context;
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)BuildPipeline;
buildPipeline = manager.Pipeline;
}
else
buildPipeline = BuildPipeline;
// Add Pipeline to the Registry
lock (_syncLock)
{
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
ref var candidate = ref _registry.Entries[i];
if (candidate.Key != key)
{
collisions++;
continue;
}
Debug.Assert(null != candidate.Pipeline);
// Has already been created
return candidate.Pipeline;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Type = type;
entry.Pipeline = buildPipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
// Return temporary pipeline
return buildPipeline;
// Create pipeline and add to Registry
object? BuildPipeline(ref BuilderContext context)
{
// Wait for right moment
while (0 != Interlocked.Increment(ref count))
{
Interlocked.Decrement(ref count);
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
try
{
// Create if required
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, factory, manager, owner);
pipeline = builder.Pipeline();
if (null != manager) manager.PipelineDelegate = pipeline;
Debug.Assert(null != pipeline);
}
var value = pipeline(ref context);
manager?.Set(value, LifetimeContainer);
return value;
}
finally
{
Interlocked.Decrement(ref count);
}
};
}
}
}

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

@ -0,0 +1,186 @@
using System;
using System.Diagnostics;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Registration;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
private ResolveDelegate<BuilderContext> PipelineFromRegistration(ref HashKey key, ExplicitRegistration registration, int position)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
Debug.Assert(null != registration.LifetimeManager);
registration.LifetimeManager.PipelineDelegate = registration.LifetimeManager switch
{
TransientLifetimeManager _ => PipelineFromRegistrationTransient(key.Type, registration, position),
SynchronizedLifetimeManager _ => PipelineFromRegistrationSynchronized(key.Type, registration),
PerResolveLifetimeManager _ => PipelineFromRegistrationPerResolve(key.Type, registration),
_ => PipelineFromRegistrationDefault(key.Type, registration)
};
return registration.LifetimeManager.Pipeline;
}
private ResolveDelegate<BuilderContext> PipelineFromRegistrationTransient(Type type, ExplicitRegistration registration, int position)
{
ResolveDelegate<BuilderContext>? pipeline = null;
return (ref BuilderContext context) =>
{
if (null != pipeline) return pipeline(ref context);
lock (registration)
{
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, registration);
pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
Debug.Assert(null != _registry);
lock (_syncLock)
{
_registry.Entries[position].Pipeline = pipeline;
}
}
return pipeline(ref context);
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromRegistrationSynchronized(Type type, ExplicitRegistration registration)
{
ResolveDelegate<BuilderContext>? pipeline = null;
var manager = registration.LifetimeManager as SynchronizedLifetimeManager;
Debug.Assert(null != manager);
return (ref BuilderContext context) =>
{
object value;
if (null != pipeline)
{
value = manager.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
return pipeline(ref context);
}
lock (registration)
{
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, registration);
pipeline = builder.Pipeline();
manager.PipelineDelegate = pipeline;
Debug.Assert(null != pipeline);
}
}
value = manager.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
try
{
// Build withing the scope
return pipeline(ref context);
}
catch
{
manager.Recover();
throw;
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromRegistrationPerResolve(Type type, ExplicitRegistration registration)
{
ResolveDelegate<BuilderContext>? pipeline = null;
Debug.Assert(null != registration.LifetimeManager);
return (ref BuilderContext context) =>
{
object value;
LifetimeManager? lifetime;
if (null != pipeline)
{
if (null != (lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager))))
{
value = lifetime.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
}
return pipeline(ref context);
}
lock (registration)
{
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, registration);
pipeline = builder.Pipeline();
registration.LifetimeManager.PipelineDelegate = pipeline;
Debug.Assert(null != pipeline);
}
}
if (null != (lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager))))
{
value = lifetime.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
}
return pipeline(ref context);
};
}
private ResolveDelegate<BuilderContext> PipelineFromRegistrationDefault(Type type, ExplicitRegistration registration)
{
ResolveDelegate<BuilderContext>? pipeline = null;
Debug.Assert(null != registration.LifetimeManager);
return (ref BuilderContext context) =>
{
object value;
if (null != pipeline)
{
value = registration.LifetimeManager.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
return pipeline(ref context);
}
lock (registration)
{
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, registration);
pipeline = builder.Pipeline();
registration.LifetimeManager.PipelineDelegate = pipeline;
Debug.Assert(null != pipeline);
}
}
value = registration.LifetimeManager.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
return pipeline(ref context);
};
}
}
}

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

@ -0,0 +1,97 @@
using System.Diagnostics;
using System.Threading;
using Unity.Builder;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
private ResolveDelegate<BuilderContext> PipelineFromTypeFactory(ref HashKey key, UnityContainer container, TypeFactoryDelegate typeFactory)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
var type = key.Type;
var name = key.Name;
var owner = this;
int count = -1;
int position = 0;
var collisions = 0;
ResolveDelegate<BuilderContext>? pipeline = null;
// Add Pipeline to the Registry
lock (_syncLock)
{
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
ref var candidate = ref _registry.Entries[i];
if (candidate.Key != key)
{
collisions++;
continue;
}
Debug.Assert(null != candidate.Pipeline);
// Has already been created
return candidate.Pipeline;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Type = type;
entry.Pipeline = BuildPipeline;
entry.Next = _registry.Buckets[targetBucket];
position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
// Return temporary pipeline
return BuildPipeline;
// Create pipeline and add to Registry
object? BuildPipeline(ref BuilderContext context)
{
// Wait for right moment
while (0 != Interlocked.Increment(ref count))
{
Interlocked.Decrement(ref count);
#if NETSTANDARD1_0 || NETCOREAPP1_0
for (var i = 0; i < 100; i++) ;
#else
Thread.SpinWait(100);
#endif
}
try
{
// Create if required
if (null == pipeline)
{
pipeline = typeFactory(type, container);
Debug.Assert(null != pipeline);
}
return pipeline(ref context);
}
finally
{
Interlocked.Decrement(ref count);
}
};
}
}
}

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

@ -0,0 +1,172 @@
using System;
using System.Diagnostics;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
private ResolveDelegate<BuilderContext> PipelineFromUnregisteredType(ref HashKey key)
{
Debug.Assert(null != _registry);
Debug.Assert(null != key.Type);
LifetimeManager manager;
lock (_syncLock)
{
var collisions = 0;
var targetBucket = key.HashCode % _registry.Buckets.Length;
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
{
ref var candidate = ref _registry.Entries[i];
if (candidate.Key != key)
{
collisions++;
continue;
}
// TODO: Check if null pipeline is possible
if (null == candidate.Pipeline)
{
// Create or get Lifetime Manager
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = manager switch
{
TransientLifetimeManager transient => PipelineFromUnregisteredTypeTransient(key.Type, transient, _registry.Count),
PerResolveLifetimeManager peresolve => PipelineFromUnregisteredTypePerResolve(key.Type, peresolve),
_ => PipelineFromUnregisteredTypeDefault(key.Type, manager)
};
candidate.Pipeline = manager.Pipeline;
}
// Replaced registration
return candidate.Pipeline;
}
// Expand if required
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
{
_registry = new Registry(_registry);
targetBucket = key.HashCode % _registry.Buckets.Length;
}
// Create a Lifetime Manager
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
manager.PipelineDelegate = manager switch
{
TransientLifetimeManager transient => PipelineFromUnregisteredTypeTransient(key.Type, transient, _registry.Count),
PerResolveLifetimeManager peresolve => PipelineFromUnregisteredTypePerResolve(key.Type, peresolve),
_ => PipelineFromUnregisteredTypeDefault(key.Type, manager)
};
Debug.Assert(null != key.Type);
// Create new entry
ref var entry = ref _registry.Entries[_registry.Count];
entry.Key = key;
entry.Next = _registry.Buckets[targetBucket];
entry.Type = key.Type;
entry.IsExplicit = true;
entry.Pipeline = manager.Pipeline;
int position = _registry.Count++;
_registry.Buckets[targetBucket] = position;
}
return manager.Pipeline;
}
private ResolveDelegate<BuilderContext> PipelineFromUnregisteredTypeTransient(Type type, TransientLifetimeManager manager, int position)
{
ResolveDelegate<BuilderContext>? pipeline = null;
return (ref BuilderContext context) =>
{
lock (manager)
{
// Create if required
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, this, Context.TypePipelineCache);
pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
Debug.Assert(null != _registry);
// Replace pipeline in storage
lock (_syncLock)
{
_registry.Entries[position].Pipeline = pipeline;
}
}
return pipeline(ref context);
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromUnregisteredTypePerResolve(Type type, PerResolveLifetimeManager manager)
{
ResolveDelegate<BuilderContext>? pipeline = null;
return (ref BuilderContext context) =>
{
lock (manager)
{
// Create if required
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, this, Context.TypePipelineCache);
pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
manager.PipelineDelegate = pipeline;
return pipeline(ref context);
}
var lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager));
Debug.Assert(null != lifetime);
var value = lifetime.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
return pipeline(ref context);
}
};
}
private ResolveDelegate<BuilderContext> PipelineFromUnregisteredTypeDefault(Type type, LifetimeManager manager)
{
ResolveDelegate<BuilderContext>? pipeline = null;
return (ref BuilderContext context) =>
{
lock (manager)
{
// Create if required
if (null == pipeline)
{
PipelineBuilder builder = new PipelineBuilder(type, this, Context.TypePipelineCache);
pipeline = builder.Pipeline();
Debug.Assert(null != pipeline);
manager.PipelineDelegate = pipeline;
}
var value = manager.Get(LifetimeContainer);
if (LifetimeManager.NoValue != value) return value;
return pipeline(ref context);
}
};
}
}
}

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

@ -4,7 +4,6 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Unity.Builder;
using Unity.Events;
using Unity.Extension;

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

@ -0,0 +1,15 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Resolution;
namespace Unity
{
public partial class UnityContainer
{
}
}

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

@ -0,0 +1,161 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Resolution;
using Unity.Storage;
using Unity.Utility;
namespace Unity
{
public partial class UnityContainer
{
#region Fields
private static readonly MethodInfo EnumerableMethod =
typeof(UnityContainer).GetTypeInfo()
.GetDeclaredMethod(nameof(UnityContainer.EnumerableHandler));
private static readonly MethodInfo EnumerableFactory =
typeof(UnityContainer).GetTypeInfo()
.GetDeclaredMethod(nameof(UnityContainer.ResolverFactory));
#endregion
#region TypeResolverFactory
public static TypeFactoryDelegate EnumerableTypeFactory = (Type type, UnityContainer container) =>
{
#if NETSTANDARD1_0 || NETCOREAPP1_0 || NET40
var typeArgument = type.GetTypeInfo().GenericTypeArguments.First();
if (typeArgument.GetTypeInfo().IsGenericType)
#else
Debug.Assert(0 < type.GenericTypeArguments.Length);
var typeArgument = type.GenericTypeArguments.First();
if (typeArgument.IsGenericType)
#endif
{
return ((EnumerableFactoryDelegate)
EnumerableFactory.MakeGenericMethod(typeArgument)
.CreateDelegate(typeof(EnumerableFactoryDelegate)))();
}
else
{
return (ResolveDelegate<BuilderContext>)
EnumerableMethod.MakeGenericMethod(typeArgument)
.CreateDelegate(typeof(ResolveDelegate<BuilderContext>));
}
};
#endregion
#region Implementation
private static object EnumerableHandler<TElement>(ref BuilderContext context)
{
return ((UnityContainer)context.Container).ResolveEnumerable<TElement>(context.Resolve,
context.Name);
}
private static ResolveDelegate<BuilderContext> ResolverFactory<TElement>()
{
Type type = typeof(TElement).GetGenericTypeDefinition();
return (ref BuilderContext c) => ((UnityContainer)c.Container).ResolveEnumerable<TElement>(c.Resolve, type, c.Name);
}
#endregion
#region Nested Types
private delegate ResolveDelegate<BuilderContext> EnumerableFactoryDelegate();
#endregion
#region Enumerator
private class EnumerableEnumerator<TType> : IEnumerator<TType>
{
#region Fields
private int _prime = 5;
private int[] Buckets;
private Entry[] Entries;
UnityContainer _container;
private int Count;
#endregion
#region Constructors
public EnumerableEnumerator(UnityContainer container)
{
_container = container;
var size = HashHelpers.Primes[_prime];
Buckets = new int[size];
Entries = new Entry[size];
#if !NET40
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
}
#endregion
#region IEnumerator
public TType Current => throw new NotImplementedException();
object IEnumerator.Current => throw new NotImplementedException();
public void Dispose()
{
throw new NotImplementedException();
}
public bool MoveNext()
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
#endregion
}
#endregion
#region Entry Type
private struct Entry
{
public HashKey Key;
public int Next;
}
#endregion
}
}

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

@ -263,7 +263,7 @@ namespace Unity
return argType;
}
internal IEnumerable<TElement> ResolveArray<TElement>(Func<Type, IRegistration, object?> resolve, Type type)
internal IEnumerable<TElement> ResolveArray<TElement>(Func<Type, string?, object?> resolve, Type type)
{
object? value;
var set = new QuickSet();
@ -292,7 +292,7 @@ namespace Unity
{
try
{
value = resolve(typeof(TElement), registration);
value = resolve(typeof(TElement), registration.Name);
}
catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
{
@ -308,7 +308,7 @@ namespace Unity
}
}
internal IEnumerable<TElement> ResolveArray<TElement>(Func<Type, IRegistration, object?> resolve,
internal IEnumerable<TElement> ResolveArray<TElement>(Func<Type, string?, object?> resolve,
Type type, Type typeDefinition)
{
object? value;
@ -340,7 +340,7 @@ namespace Unity
{
try
{
value = resolve(typeof(TElement), registration);
value = resolve(typeof(TElement), registration.Name);
}
catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
{
@ -367,9 +367,7 @@ namespace Unity
{
try
{
var itemKey = new HashKey(typeof(TElement), registration.Name);
var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration);
value = resolve(typeof(TElement), item);
value = resolve(typeof(TElement), registration.Name);
}
catch (MakeGenericTypeFailedException) { continue; }
catch (InvalidRegistrationException) { continue; }
@ -383,7 +381,7 @@ namespace Unity
}
}
internal IEnumerable<TElement> ComplexArray<TElement>(Func<Type, IRegistration, object?> resolve, Type type)
internal IEnumerable<TElement> ComplexArray<TElement>(Func<Type, string?, object?> resolve, Type type)
{
object? value;
var set = new QuickSet();
@ -413,9 +411,7 @@ namespace Unity
{
try
{
var itemKey = new HashKey(typeof(TElement), registration.Name);
var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration);
value = resolve(typeof(TElement), item);
value = resolve(typeof(TElement), registration.Name);
}
catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
{
@ -431,7 +427,7 @@ namespace Unity
}
}
internal IEnumerable<TElement> ComplexArray<TElement>(Func<Type, IRegistration, object?> resolve,
internal IEnumerable<TElement> ComplexArray<TElement>(Func<Type, string?, object?> resolve,
Type type, Type typeDefinition)
{
object? value;
@ -462,9 +458,7 @@ namespace Unity
{
try
{
var itemKey = new HashKey(typeof(TElement), registration.Name);
var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name);
value = resolve(typeof(TElement), item);
value = resolve(typeof(TElement), registration.Name);
}
catch (ArgumentException ex) when (ex.InnerException is TypeLoadException)
{
@ -491,10 +485,8 @@ namespace Unity
{
try
{
var itemKey = new HashKey(typeof(TElement), registration.Name);
var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name);
#pragma warning disable CS8601 // Possible null reference assignment.
value = (TElement)resolve(typeof(TElement), item);
value = (TElement)resolve(typeof(TElement), registration.Name);
#pragma warning restore CS8601 // Possible null reference assignment.
}
catch (MakeGenericTypeFailedException) { continue; }