Upgrading pipeline build
This commit is contained in:
Родитель
bacb641231
Коммит
c5069321ce
|
@ -21,8 +21,6 @@ namespace Unity.Builder
|
|||
{
|
||||
#region Fields
|
||||
|
||||
private bool _async;
|
||||
|
||||
internal IPolicyList List { get; set; }
|
||||
public delegate object? ResolvePlanDelegate(ref BuilderContext context, ResolveDelegate<BuilderContext> resolver);
|
||||
|
||||
|
@ -35,7 +33,7 @@ namespace Unity.Builder
|
|||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public string? Name => Registration.Name;
|
||||
public string? Name { get; set; }
|
||||
|
||||
public object? Resolve(Type type, string? name)
|
||||
{
|
||||
|
@ -74,7 +72,7 @@ namespace Unity.Builder
|
|||
public object? Get(Type policyInterface)
|
||||
{
|
||||
return List?.Get(Type, Name, policyInterface) ??
|
||||
Registration.Get(policyInterface);
|
||||
Registration?.Get(policyInterface);
|
||||
}
|
||||
|
||||
public object? Get(Type type, Type policyInterface)
|
||||
|
@ -86,7 +84,7 @@ namespace Unity.Builder
|
|||
{
|
||||
return List?.Get(type, name, policyInterface) ?? (type != Type || name != Name
|
||||
? ContainerContext.Get(type, name, policyInterface)
|
||||
: Registration.Get(policyInterface));
|
||||
: Registration?.Get(policyInterface));
|
||||
}
|
||||
|
||||
public void Set(Type policyInterface, object policy)
|
||||
|
@ -118,13 +116,12 @@ namespace Unity.Builder
|
|||
|
||||
public bool IsAsync { get; set; }
|
||||
|
||||
public bool Async { get => _async; set => _async = value; }
|
||||
|
||||
public ResolverOverride[] Overrides;
|
||||
|
||||
public object? Existing { get; set; }
|
||||
|
||||
public IRegistration Registration { get; set; }
|
||||
public IRegistration? Registration { get; set; }
|
||||
|
||||
public ContainerContext ContainerContext { get; set; }
|
||||
|
||||
|
@ -138,7 +135,9 @@ namespace Unity.Builder
|
|||
{
|
||||
get
|
||||
{
|
||||
if (null != Registration.PipelineDelegate) return Registration.PipelineDelegate;
|
||||
if (null != Registration?.PipelineDelegate) return Registration.PipelineDelegate;
|
||||
|
||||
Debug.Assert(null != Registration);
|
||||
|
||||
lock (Registration)
|
||||
{
|
||||
|
|
|
@ -24,12 +24,12 @@ namespace Unity.Factories
|
|||
|
||||
#region TypeResolverFactory
|
||||
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration policies) =>
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration? policies) =>
|
||||
{
|
||||
var typeArgument = type.GetElementType();
|
||||
var targetType = policies.Owner.GetTargetType(typeArgument);
|
||||
var targetType = policies?.Owner.GetTargetType(typeArgument);
|
||||
|
||||
if (typeArgument != targetType)
|
||||
if (null != targetType && typeArgument != targetType)
|
||||
{
|
||||
return ((BuiltInFactoryDelegate)BuiltInMethod
|
||||
.MakeGenericMethod(typeArgument)
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Unity.Factories
|
|||
|
||||
#region TypeResolverFactory
|
||||
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration policies) =>
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration? policies) =>
|
||||
{
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0 || NET40
|
||||
var typeArgument = type.GetTypeInfo().GenericTypeArguments.First();
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Unity.Factories
|
|||
|
||||
#region TypeResolverFactory
|
||||
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration policies) =>
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration? policies) =>
|
||||
{
|
||||
var typeToBuild = type.GetTypeInfo().GenericTypeArguments[0];
|
||||
var factoryMethod = ImplementationMethod.MakeGenericMethod(typeToBuild);
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Unity.Factories
|
|||
|
||||
#region TypeResolverFactory
|
||||
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration policies) =>
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration? policies) =>
|
||||
{
|
||||
var itemType = type.GetTypeInfo().GenericTypeArguments[0];
|
||||
var lazyMethod = ImplementationMethod.MakeGenericMethod(itemType);
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Unity.Factories
|
|||
|
||||
#region ResolveDelegateFactory
|
||||
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration policies) =>
|
||||
public static TypeFactoryDelegate Factory = (Type type, IRegistration? policies) =>
|
||||
{
|
||||
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0 || NET40
|
||||
|
|
|
@ -5,5 +5,5 @@ using Unity.Resolution;
|
|||
|
||||
namespace Unity
|
||||
{
|
||||
public delegate ResolveDelegate<BuilderContext> TypeFactoryDelegate(Type type, IRegistration policies);
|
||||
public delegate ResolveDelegate<BuilderContext> TypeFactoryDelegate(Type type, IRegistration? policies);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ using Unity.Registration;
|
|||
|
||||
namespace Unity
|
||||
{
|
||||
public delegate IEnumerable<object> MemberSelector<TMember>(Type type, IRegistration set)
|
||||
public delegate IEnumerable<object> MemberSelector<TMember>(Type type, IRegistration? set)
|
||||
where TMember : MemberInfo;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
|
@ -8,34 +9,44 @@ namespace Unity
|
|||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private PipelineDelegate DefaultLifetime()
|
||||
private BuildPipelineAsync DefaultLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var manager = Registration.LifetimeManager;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var registration = Registration;
|
||||
var synchronized = manager as SynchronizedLifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// In Sync mode just execute pipeline
|
||||
if (!context.Async)
|
||||
if (!context.RunAsync)
|
||||
{
|
||||
var value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
value = pipeline(ref c);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
|
@ -54,11 +65,9 @@ namespace Unity
|
|||
}
|
||||
|
||||
// Async mode
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew(() =>
|
||||
var task = Task.Factory.StartNew<object?>(() =>
|
||||
{
|
||||
var value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
@ -90,5 +99,50 @@ namespace Unity
|
|||
return new ValueTask<object?>(task);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private PipelineDelegate DefaultLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var registration = Registration;
|
||||
var synchronized = manager as SynchronizedLifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
|
||||
var value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
try
|
||||
{
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
catch (Exception ex)// when (null != synchronized)
|
||||
{
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
synchronized?.Recover();
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,53 +7,47 @@ namespace Unity
|
|||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private PipelineDelegate PerResolveLifetime()
|
||||
private BuildPipelineAsync PerResolveLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
object value;
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// In Sync mode just execute pipeline
|
||||
if (!context.Async)
|
||||
if (!context.RunAsync)
|
||||
{
|
||||
// Get it from context
|
||||
var manager = (LifetimeManager?)context.Get(typeof(LifetimeManager));
|
||||
|
||||
// Return if holds value
|
||||
if (null != manager)
|
||||
var c = new BuilderContext
|
||||
{
|
||||
value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
{
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
};
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
value = pipeline(ref c);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
// Async mode
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew(() =>
|
||||
var task = Task.Factory.StartNew<object?>(() =>
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
ContainerContext = unity,
|
||||
|
@ -69,5 +63,41 @@ namespace Unity
|
|||
return new ValueTask<object?>(task);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private PipelineDelegate PerResolveLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
object value;
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
|
||||
// Get it from context
|
||||
var manager = (LifetimeManager?)context.Get(typeof(LifetimeManager));
|
||||
|
||||
// Return if holds value
|
||||
if (null != manager)
|
||||
{
|
||||
value = manager.GetValue(lifetime);
|
||||
if (LifetimeManager.NoValue != value)
|
||||
{
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref context);
|
||||
return new ValueTask<object?>(value);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Exceptions;
|
||||
|
@ -9,18 +10,19 @@ namespace Unity
|
|||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private PipelineDelegate PerThreadLifetime()
|
||||
private BuildPipelineAsync PerThreadLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var manager = Registration.LifetimeManager;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
// Verify is not async
|
||||
if (context.IsAsync)
|
||||
if (context.RunAsync || context.RunningAsync)
|
||||
{
|
||||
var ex = new InvalidRegistrationException("Lifetime:PerThread is not designed to participate in async operations");
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
|
@ -33,6 +35,78 @@ namespace Unity
|
|||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
// Compose
|
||||
try
|
||||
{
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
var lifetime = context.ContainerContext.Lifetime;
|
||||
var value = manager.GetValue(lifetime);
|
||||
|
||||
if (LifetimeManager.NoValue != value)
|
||||
return new ValueTask<object?>(value);
|
||||
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
Name = name,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
Parent = IntPtr.Zero,
|
||||
};
|
||||
|
||||
// Compose down the chain
|
||||
value = pipeline(ref c);
|
||||
manager.SetValue(value, lifetime);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
catch (Exception ex)// when (null != synchronized)
|
||||
{
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private PipelineDelegate PerThreadLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var manager = Registration?.LifetimeManager;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
// Verify is not async
|
||||
if (context.IsAsync)
|
||||
{
|
||||
var ex = new InvalidRegistrationException("Lifetime:PerThread is not designed to participate in async operations");
|
||||
#if NET40 || NET45 || NETSTANDARD1_0
|
||||
var taskSource = new TaskCompletionSource<object?>();
|
||||
taskSource.SetException(ex);
|
||||
var ext = taskSource.Task;
|
||||
#else
|
||||
var ext = Task.FromException<object?>(ex);
|
||||
#endif
|
||||
return new ValueTask<object?>(ext);
|
||||
}
|
||||
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
// Compose
|
||||
try
|
||||
{
|
||||
|
|
|
@ -7,38 +7,49 @@ namespace Unity
|
|||
{
|
||||
public ref partial struct PipelineBuilder
|
||||
{
|
||||
private PipelineDelegate TransientLifetime()
|
||||
private BuildPipelineAsync TransientLifetimeAsync()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
return (ref PipelineContext context) =>
|
||||
{
|
||||
//In Sync mode just execute pipeline
|
||||
if (!context.Async)
|
||||
{
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
var value = pipeline(ref context);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
// Async mode
|
||||
var unity = context.ContainerContext;
|
||||
var overrides = context.Overrides;
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew(() =>
|
||||
//In Sync mode just execute pipeline
|
||||
if (!context.RunAsync)
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
Name = name,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
DeclaringType = type,
|
||||
Parent = IntPtr.Zero,
|
||||
};
|
||||
|
||||
// Execute pipeline
|
||||
var value = pipeline(ref c);
|
||||
return new ValueTask<object?>(value);
|
||||
}
|
||||
|
||||
// Create and return a task that creates an object
|
||||
var task = Task.Factory.StartNew<object?>(() =>
|
||||
{
|
||||
var c = new BuilderContext
|
||||
{
|
||||
List = new PolicyList(),
|
||||
IsAsync = true,
|
||||
Type = type,
|
||||
Name = name,
|
||||
ContainerContext = unity,
|
||||
Registration = registration,
|
||||
Overrides = overrides,
|
||||
|
@ -53,5 +64,23 @@ namespace Unity
|
|||
return new ValueTask<object?>(task);
|
||||
};
|
||||
}
|
||||
|
||||
private PipelineDelegate TransientLifetime()
|
||||
{
|
||||
var type = Type;
|
||||
var name = Name;
|
||||
var registration = Registration;
|
||||
var pipeline = Pipeline() ?? ((ref BuilderContext c) => throw new ResolutionFailedException(type, name, error));
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
// Set Policy storage if required
|
||||
if (null == context.List)
|
||||
context.List = new PolicyList();
|
||||
|
||||
var value = pipeline(ref context);
|
||||
return new ValueTask<object?>(value);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,20 +37,22 @@ namespace Unity
|
|||
|
||||
Seed = Registration.Pipeline;
|
||||
_enumerator = pipelines.GetEnumerator();
|
||||
Debug.Assert(null != _enumerator);
|
||||
}
|
||||
|
||||
public PipelineBuilder(ref PipelineContext context)
|
||||
public PipelineBuilder(ref PipelineContext context, IRegistration? registration = null)
|
||||
{
|
||||
Seed = null;
|
||||
Type = context.Type;
|
||||
Name = context.Name;
|
||||
Registration = null;
|
||||
Registration = registration;
|
||||
ContainerContext = context.ContainerContext;
|
||||
|
||||
_enumerator = context.ContainerContext
|
||||
.TypePipelineCache
|
||||
.AsEnumerable<Pipeline>()
|
||||
.GetEnumerator();
|
||||
_enumerator = registration?.Processors?.GetEnumerator() ??
|
||||
context.ContainerContext
|
||||
.TypePipelineCache
|
||||
.AsEnumerable<Pipeline>()
|
||||
.GetEnumerator();
|
||||
}
|
||||
|
||||
public PipelineBuilder(ref BuilderContext context)
|
||||
|
@ -60,8 +62,9 @@ namespace Unity
|
|||
Registration = context.Registration;
|
||||
ContainerContext = context.ContainerContext;
|
||||
|
||||
Seed = Registration.Pipeline;
|
||||
_enumerator = (context.Registration.Processors ?? Enumerable.Empty<Pipeline>()).GetEnumerator();
|
||||
Seed = Registration?.Pipeline;
|
||||
_enumerator = (context.Registration?.Processors ??
|
||||
Enumerable.Empty<Pipeline>()).GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -88,7 +91,7 @@ namespace Unity
|
|||
{
|
||||
ref var context = ref this;
|
||||
return _enumerator?.MoveNext() ?? false
|
||||
? _enumerator.Current.Build(ref context)
|
||||
? _enumerator?.Current?.Build(ref context) ?? Seed
|
||||
: Seed;
|
||||
}
|
||||
|
||||
|
@ -98,7 +101,7 @@ namespace Unity
|
|||
|
||||
ref var context = ref this;
|
||||
return _enumerator?.MoveNext() ?? false
|
||||
? _enumerator.Current.Build(ref context)
|
||||
? _enumerator?.Current.Build(ref context) ?? Seed
|
||||
: Seed;
|
||||
}
|
||||
|
||||
|
@ -116,6 +119,20 @@ namespace Unity
|
|||
};
|
||||
}
|
||||
|
||||
public BuildPipelineAsync BuildPipelineAsync()
|
||||
{
|
||||
var manager = Registration?.LifetimeManager;
|
||||
|
||||
return manager switch
|
||||
{
|
||||
null => TransientLifetimeAsync(),
|
||||
TransientLifetimeManager _ => TransientLifetimeAsync(),
|
||||
PerResolveLifetimeManager _ => PerResolveLifetimeAsync(),
|
||||
PerThreadLifetimeManager _ => PerThreadLifetimeAsync(),
|
||||
_ => DefaultLifetimeAsync()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -75,12 +75,12 @@ namespace Unity
|
|||
|
||||
#region Selection
|
||||
|
||||
public override IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public override IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
var members = new List<InjectionMember>();
|
||||
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<ConstructorInfo, object[]>)
|
||||
{
|
||||
|
|
|
@ -38,8 +38,8 @@ namespace Unity
|
|||
.Where(ctor => !ctor.IsFamily && !ctor.IsPrivate && !ctor.IsStatic);
|
||||
}
|
||||
|
||||
public override MemberSelector<ConstructorInfo> GetOrDefault(IPolicySet registration) =>
|
||||
registration.Get<MemberSelector<ConstructorInfo>>() ??
|
||||
public override MemberSelector<ConstructorInfo> GetOrDefault(IPolicySet? registration) =>
|
||||
registration?.Get<MemberSelector<ConstructorInfo>>() ??
|
||||
Defaults.SelectConstructor;
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -77,7 +77,7 @@ namespace Unity
|
|||
};
|
||||
}
|
||||
|
||||
var lifetimeManager = (LifetimeManager?)builder.Registration.Get(typeof(LifetimeManager));
|
||||
var lifetimeManager = (LifetimeManager?)builder.Registration?.Get(typeof(LifetimeManager));
|
||||
|
||||
return lifetimeManager is PerResolveLifetimeManager
|
||||
? GetPerResolveDelegate(info, resolvers, pipeline)
|
||||
|
|
|
@ -12,10 +12,10 @@ namespace Unity
|
|||
public partial class ConstructorPipeline
|
||||
{
|
||||
|
||||
public override IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public override IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<ConstructorInfo, object[]>)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Unity.Builder;
|
||||
|
@ -28,7 +29,8 @@ namespace Unity
|
|||
|
||||
// Try to get resolver
|
||||
Type? generic = null;
|
||||
var resolver = builder.Registration.Get(typeof(ResolveDelegate<BuilderContext>)) ??
|
||||
var resolver = builder.Registration?.Pipeline ??
|
||||
builder.Registration?.Get(typeof(ResolveDelegate<BuilderContext>)) ??
|
||||
builder.ContainerContext.Get(builder.Type, typeof(ResolveDelegate<BuilderContext>));
|
||||
|
||||
if (null == resolver)
|
||||
|
@ -40,7 +42,7 @@ namespace Unity
|
|||
#endif
|
||||
{
|
||||
generic = builder.Type.GetGenericTypeDefinition();
|
||||
resolver = builder.ContainerContext.Get(generic, builder.Registration.Name, typeof(ResolveDelegate<BuilderContext>)) ??
|
||||
resolver = builder.ContainerContext.Get(generic, builder.Name, typeof(ResolveDelegate<BuilderContext>)) ??
|
||||
builder.ContainerContext.Get(generic, typeof(ResolveDelegate<BuilderContext>));
|
||||
}
|
||||
}
|
||||
|
@ -49,9 +51,9 @@ namespace Unity
|
|||
if (null != resolver) return builder.Pipeline((ResolveDelegate<BuilderContext>)resolver);
|
||||
|
||||
// Try finding factory
|
||||
TypeFactoryDelegate? factory = builder.Registration.Get<TypeFactoryDelegate>();
|
||||
TypeFactoryDelegate? factory = builder.Registration?.Get<TypeFactoryDelegate>();
|
||||
|
||||
if (builder.Registration is ExplicitRegistration registration)
|
||||
if (builder.Registration is ExplicitRegistration @explicit)
|
||||
{
|
||||
#if NETCOREAPP1_0 || NETSTANDARD1_0
|
||||
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
|
||||
|
@ -62,7 +64,7 @@ namespace Unity
|
|||
factory = (TypeFactoryDelegate?)builder.ContainerContext.Get(builder.Type.GetGenericTypeDefinition(),
|
||||
typeof(TypeFactoryDelegate));
|
||||
}
|
||||
else if (builder.Type.IsArray)
|
||||
else if (null != builder.Type && builder.Type.IsArray)
|
||||
{
|
||||
if (builder.Type.GetArrayRank() == 1)
|
||||
{
|
||||
|
@ -76,21 +78,21 @@ namespace Unity
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(builder.Registration is ExplicitRegistration @implicit)
|
||||
{
|
||||
#if NETCOREAPP1_0 || NETSTANDARD1_0
|
||||
if (builder.Type.GetTypeInfo().IsGenericType)
|
||||
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
|
||||
#else
|
||||
if (builder.Type.IsGenericType)
|
||||
if (null != builder.Type && builder.Type.IsGenericType)
|
||||
#endif
|
||||
{
|
||||
factory = (TypeFactoryDelegate?)builder.ContainerContext.Get(builder.Type.GetGenericTypeDefinition(),
|
||||
typeof(TypeFactoryDelegate));
|
||||
}
|
||||
else if (builder.Type.IsArray)
|
||||
else if (builder.Type?.IsArray ?? false)
|
||||
{
|
||||
if (builder.Type.GetArrayRank() == 1)
|
||||
return builder.Pipeline(ArrayResolver.Factory(builder.Type, builder.Registration));
|
||||
if (builder.Type?.GetArrayRank() == 1)
|
||||
return builder.Pipeline(ArrayResolver.Factory(builder.Type, @implicit));
|
||||
else
|
||||
{
|
||||
var message = $"Invalid array {builder.Type}. Only arrays of rank 1 are supported";
|
||||
|
@ -99,6 +101,8 @@ namespace Unity
|
|||
}
|
||||
}
|
||||
|
||||
Debug.Assert(null != builder.Type);
|
||||
|
||||
return null != factory
|
||||
? builder.Pipeline(factory(builder.Type, builder.Registration))
|
||||
: builder.Pipeline();
|
||||
|
|
|
@ -24,12 +24,12 @@ namespace Unity
|
|||
|
||||
#region Overrides
|
||||
|
||||
public override IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public override IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
HashSet<object> memberSet = new HashSet<object>();
|
||||
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<FieldInfo, object> && memberSet.Add(injectionMember))
|
||||
yield return injectionMember;
|
||||
|
|
|
@ -32,8 +32,8 @@ namespace Unity
|
|||
|
||||
protected override Type MemberType(FieldInfo info) => info.FieldType;
|
||||
|
||||
public override MemberSelector<FieldInfo> GetOrDefault(IPolicySet registration) =>
|
||||
registration.Get<MemberSelector<FieldInfo>>() ?? Defaults.SelectField;
|
||||
public override MemberSelector<FieldInfo> GetOrDefault(IPolicySet? registration) =>
|
||||
registration?.Get<MemberSelector<FieldInfo>>() ?? Defaults.SelectField;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -12,24 +12,24 @@ namespace Unity
|
|||
{
|
||||
var requestedType = builder.Type;
|
||||
|
||||
if (builder.Registration is ExplicitRegistration registration)
|
||||
if (builder.Registration is ExplicitRegistration @explicit)
|
||||
{
|
||||
// Explicit Registration
|
||||
if (null == registration.Type) return builder.Pipeline();
|
||||
if (null == @explicit.Type) return builder.Pipeline();
|
||||
|
||||
builder.Type = (null == registration.BuildType)
|
||||
? registration.Type
|
||||
: registration.BuildType(registration.Type);
|
||||
builder.Type = (null == @explicit.BuildType)
|
||||
? @explicit.Type
|
||||
: @explicit.BuildType(@explicit.Type);
|
||||
}
|
||||
else
|
||||
else if (builder.Registration is ImplicitRegistration @implicit)
|
||||
{
|
||||
// Implicit Registration
|
||||
if (null != builder.Registration.BuildType)
|
||||
builder.Type = builder.Registration.BuildType(builder.Type);
|
||||
if (null != @implicit.BuildType)
|
||||
builder.Type = @implicit.BuildType(builder.Type);
|
||||
}
|
||||
|
||||
// If nothing to map or build required, just create it
|
||||
if (builder.Registration.BuildRequired || requestedType == builder.Type)
|
||||
if ((builder.Registration?.BuildRequired ?? false) || requestedType == builder.Type)
|
||||
return builder.Pipeline();
|
||||
|
||||
var type = builder.Type;
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace Unity
|
|||
/// <param name="type"></param>
|
||||
/// <param name="registration"></param>
|
||||
/// <returns></returns>
|
||||
public IEnumerable<Expression> GetExpressions(Type type, IRegistration registration)
|
||||
public IEnumerable<Expression> GetExpressions(Type type, IRegistration? registration)
|
||||
{
|
||||
var selector = GetOrDefault(registration);
|
||||
var members = selector(type, registration);
|
||||
|
@ -180,9 +180,9 @@ namespace Unity
|
|||
#endif
|
||||
}
|
||||
|
||||
public virtual MemberSelector<TMemberInfo> GetOrDefault(IPolicySet registration)
|
||||
public virtual MemberSelector<TMemberInfo> GetOrDefault(IPolicySet? registration)
|
||||
{
|
||||
return (MemberSelector<TMemberInfo>)(registration.Get(typeof(MemberSelector<TMemberInfo>)) ??
|
||||
return (MemberSelector<TMemberInfo>)(registration?.Get(typeof(MemberSelector<TMemberInfo>)) ??
|
||||
Defaults.Get(typeof(MemberSelector<TMemberInfo>)) ??
|
||||
throw new InvalidOperationException("Should never be null"));
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ namespace Unity
|
|||
{
|
||||
public abstract partial class MemberPipeline<TMemberInfo, TData>
|
||||
{
|
||||
public virtual IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public virtual IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
HashSet<object> memberSet = new HashSet<object>();
|
||||
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<TMemberInfo, TData> && memberSet.Add(injectionMember))
|
||||
yield return injectionMember;
|
||||
|
|
|
@ -26,12 +26,12 @@ namespace Unity
|
|||
|
||||
#region Overrides
|
||||
|
||||
public override IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public override IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
HashSet<object> memberSet = new HashSet<object>();
|
||||
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<MethodInfo, object[]> && memberSet.Add(injectionMember))
|
||||
yield return injectionMember;
|
||||
|
|
|
@ -31,8 +31,8 @@ namespace Unity
|
|||
!member.IsStatic);
|
||||
}
|
||||
|
||||
public override MemberSelector<MethodInfo> GetOrDefault(IPolicySet registration) =>
|
||||
registration.Get<MemberSelector<MethodInfo>>() ?? Defaults.SelectMethod;
|
||||
public override MemberSelector<MethodInfo> GetOrDefault(IPolicySet? registration) =>
|
||||
registration?.Get<MemberSelector<MethodInfo>>() ?? Defaults.SelectMethod;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@ namespace Unity
|
|||
public partial class MethodPipeline
|
||||
{
|
||||
|
||||
public override IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public override IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
HashSet<object> memberSet = new HashSet<object>();
|
||||
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<MethodInfo, object[]> && memberSet.Add(injectionMember))
|
||||
yield return injectionMember;
|
||||
|
|
|
@ -25,12 +25,12 @@ namespace Unity
|
|||
|
||||
#region Overrides
|
||||
|
||||
public override IEnumerable<object> Select(Type type, IRegistration registration)
|
||||
public override IEnumerable<object> Select(Type type, IRegistration? registration)
|
||||
{
|
||||
HashSet<object> memberSet = new HashSet<object>();
|
||||
|
||||
// Select Injected Members
|
||||
foreach (var injectionMember in registration.InjectionMembers ?? EmptyCollection)
|
||||
foreach (var injectionMember in registration?.InjectionMembers ?? EmptyCollection)
|
||||
{
|
||||
if (injectionMember is InjectionMember<PropertyInfo, object> && memberSet.Add(injectionMember))
|
||||
yield return injectionMember;
|
||||
|
@ -57,15 +57,15 @@ namespace Unity
|
|||
yield return new InvalidRegistrationException(
|
||||
$"Indexer '{member.Name}' on type '{type?.Name}' is marked for injection. Indexers cannot be injected");
|
||||
|
||||
if (setter.IsStatic)
|
||||
if (setter?.IsStatic ?? false)
|
||||
yield return new InvalidRegistrationException(
|
||||
$"Static property '{member.Name}' on type '{type?.Name}' is marked for injection. Static properties cannot be injected");
|
||||
|
||||
if (setter.IsPrivate)
|
||||
if (setter?.IsPrivate ?? false)
|
||||
yield return new InvalidRegistrationException(
|
||||
$"Private property '{member.Name}' on type '{type?.Name}' is marked for injection. Private properties cannot be injected");
|
||||
|
||||
if (setter.IsFamily)
|
||||
if (setter?.IsFamily ?? false)
|
||||
yield return new InvalidRegistrationException(
|
||||
$"Protected property '{member.Name}' on type '{type?.Name}' is marked for injection. Protected properties cannot be injected");
|
||||
|
||||
|
|
|
@ -39,8 +39,8 @@ namespace Unity
|
|||
}
|
||||
}
|
||||
|
||||
public override MemberSelector<PropertyInfo> GetOrDefault(IPolicySet registration) =>
|
||||
registration.Get<MemberSelector<PropertyInfo>>() ?? Defaults.SelectProperty;
|
||||
public override MemberSelector<PropertyInfo> GetOrDefault(IPolicySet? registration) =>
|
||||
registration?.Get<MemberSelector<PropertyInfo>>() ?? Defaults.SelectProperty;
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -104,6 +104,27 @@ namespace Unity.Storage
|
|||
|
||||
#region Public Members
|
||||
|
||||
internal void Set(Type type, string? name, BuildPipelineAsync pipeline)
|
||||
{
|
||||
var key = new HashKey(type, name);
|
||||
var targetBucket = key.HashCode % Buckets.Length;
|
||||
|
||||
for (var i = Buckets[targetBucket]; i >= 0; i = Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref Entries[i];
|
||||
if (candidate.Key != key) continue;
|
||||
|
||||
candidate.Pipeline = pipeline;
|
||||
return;
|
||||
}
|
||||
|
||||
ref var entry = ref Entries[Count];
|
||||
entry.Key = key;
|
||||
entry.Next = Buckets[targetBucket];
|
||||
entry.Pipeline = pipeline;
|
||||
Buckets[targetBucket] = Count++;
|
||||
}
|
||||
|
||||
public bool RequireToGrow => (Entries.Length - Count) < 100 &&
|
||||
(float)Count / Entries.Length > 0.72f;
|
||||
#endregion
|
||||
|
|
|
@ -150,7 +150,6 @@ namespace Unity.Storage
|
|||
Buckets[targetBucket] = Count++;
|
||||
}
|
||||
|
||||
|
||||
public bool RequireToGrow => (Entries.Length - Count) < 100 &&
|
||||
(float)Count / Entries.Length > 0.72f;
|
||||
#endregion
|
||||
|
|
|
@ -132,6 +132,9 @@ namespace Unity
|
|||
container.LifetimeContainer.Remove(disposable);
|
||||
disposable.Dispose();
|
||||
}
|
||||
|
||||
// Check what strategies to run
|
||||
registration.Processors = Context.InstancePipelineCache;
|
||||
|
||||
// Raise event
|
||||
container.RegisteringInstance?.Invoke(this, new RegisterInstanceEventArgs(registeredType, instance, name, manager));
|
||||
|
|
|
@ -133,9 +133,9 @@ namespace Unity
|
|||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
var infoFrom = typeFrom?.GetTypeInfo();
|
||||
var infoTo = typeTo?.GetTypeInfo();
|
||||
if (!infoFrom.IsGenericType && !infoTo.IsGenericType && !infoFrom.IsAssignableFrom(infoTo))
|
||||
if (null != infoTo && null != infoFrom && !infoFrom.IsGenericType && !infoTo.IsGenericType && !infoFrom.IsAssignableFrom(infoTo))
|
||||
#else
|
||||
if (!typeFrom.IsGenericType && !typeTo.IsGenericType && !typeFrom.IsAssignableFrom(typeTo))
|
||||
if (null != typeTo && null != typeFrom && !typeFrom.IsGenericType && !typeTo.IsGenericType && !typeFrom.IsAssignableFrom(typeTo))
|
||||
#endif
|
||||
throw new ArgumentException($"The type {typeTo} cannot be assigned to variables of type {typeFrom}.");
|
||||
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Builder;
|
||||
using Unity.Registration;
|
||||
using Unity.Storage;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
public partial class UnityContainer
|
||||
{
|
||||
#region Container Resolution
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private static ValueTask<object?> ResolveContainerPipeline(ref PipelineContext context)
|
||||
=> new ValueTask<object?>(context.ContainerContext.Container);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private BuildPipelineAsync? GetPipeline(Type type, string? name)
|
||||
{
|
||||
var key = new HashKey(type, name);
|
||||
|
@ -39,11 +49,141 @@ namespace Unity
|
|||
#region Root Build Pipeline
|
||||
|
||||
[SecuritySafeCritical]
|
||||
public ValueTask<object?> DefaultBuildPipeline(ref PipelineContext context)
|
||||
public ValueTask<object?> BuildPipeline(ref PipelineContext context)
|
||||
{
|
||||
var builder = new PipelineBuilder(ref PipelineContext context);
|
||||
// Get Registration if exists
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
var info = context.Type.GetTypeInfo();
|
||||
var registration = info.IsGenericType
|
||||
? GetGenericExplicitRegistration(context.Type, context.Name, info)
|
||||
: GetSimpleExplicitRegistration(context.Type, context.Name);
|
||||
#else
|
||||
var registration = context.Type.IsGenericType
|
||||
? GetGenericExplicitRegistration(context.Type, context.Name)
|
||||
: GetSimpleExplicitRegistration(context.Type, context.Name);
|
||||
#endif
|
||||
// Build Pipeline
|
||||
var builder = new PipelineBuilder(ref context, registration);
|
||||
var pipeline = builder.BuildPipelineAsync();
|
||||
|
||||
throw new NotImplementedException();
|
||||
return pipeline(ref context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Get Registration
|
||||
|
||||
|
||||
private IRegistration? GetSimpleExplicitRegistration(Type type, string? name)
|
||||
{
|
||||
var key = new HashKey(type, name);
|
||||
|
||||
// Iterate through containers hierarchy
|
||||
for (UnityContainer? container = this; null != container; container = container._parent)
|
||||
{
|
||||
// Skip to parent if no registrations
|
||||
if (null == container._metadata) continue;
|
||||
|
||||
Debug.Assert(null != container._registry);
|
||||
var registry = container._registry;
|
||||
|
||||
// Check for exact match
|
||||
for (var i = registry.Buckets[key.HashCode % registry.Buckets.Length]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != key) continue;
|
||||
|
||||
// Found a registration
|
||||
if (!(candidate.Policies is IRegistration))
|
||||
candidate.Policies = container.CreateRegistration(type, name, candidate.Policies);
|
||||
|
||||
return (IRegistration)candidate.Policies;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(null != _root);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
private IRegistration? GetGenericExplicitRegistration(Type type, string? name, TypeInfo info)
|
||||
#else
|
||||
private IRegistration? GetGenericExplicitRegistration(Type type, string? name)
|
||||
#endif
|
||||
{
|
||||
bool initGenerics = true;
|
||||
Type? generic = null;
|
||||
int targetBucket;
|
||||
var keyExact = new HashKey(type, name);
|
||||
var keyGeneric = new HashKey();
|
||||
var keyDefault = new HashKey();
|
||||
|
||||
// Iterate through containers hierarchy
|
||||
for (UnityContainer? container = this; null != container; container = container._parent)
|
||||
{
|
||||
// Skip to parent if no registrations
|
||||
if (null == container._metadata) continue;
|
||||
|
||||
Debug.Assert(null != container._registry);
|
||||
var registry = container._registry;
|
||||
|
||||
// Check for exact match
|
||||
targetBucket = keyExact.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != keyExact) continue;
|
||||
|
||||
// Found a registration
|
||||
if (!(candidate.Policies is IRegistration))
|
||||
candidate.Policies = container.CreateRegistration(type, name, candidate.Policies);
|
||||
|
||||
return (IRegistration)candidate.Policies;
|
||||
}
|
||||
|
||||
// Generic registrations
|
||||
if (initGenerics)
|
||||
{
|
||||
initGenerics = false;
|
||||
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
generic = info.GetGenericTypeDefinition();
|
||||
#else
|
||||
generic = type.GetGenericTypeDefinition();
|
||||
#endif
|
||||
keyGeneric = new HashKey(generic, name);
|
||||
keyDefault = new HashKey(generic);
|
||||
}
|
||||
|
||||
// Check for factory with same name
|
||||
targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != keyGeneric)
|
||||
continue;
|
||||
|
||||
// Found a factory
|
||||
return container.GetOrAdd(ref keyExact, type, name, candidate.Policies);
|
||||
}
|
||||
|
||||
// Check for default factory
|
||||
targetBucket = keyDefault.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
ref var candidate = ref registry.Entries[i];
|
||||
if (candidate.Key != keyDefault)
|
||||
continue;
|
||||
|
||||
// Found a factory
|
||||
return container.GetOrAdd(ref keyExact, type, name, candidate.Policies);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -62,16 +62,18 @@ namespace Unity
|
|||
// IUnityContainer, IUnityContainerAsync
|
||||
var container = new ExplicitRegistration(this, null, typeof(UnityContainer))
|
||||
{
|
||||
Pipeline = (ref BuilderContext c) => c.Async ? (object)Task.FromResult<object>(c.Container) : c.Container,
|
||||
Pipeline = (ref BuilderContext c) => c.Container,
|
||||
PipelineDelegate = (ref BuilderContext c) => new ValueTask<object?>(c.Container)
|
||||
};
|
||||
|
||||
// Create Registry
|
||||
// Create Registries
|
||||
_metadata = new Metadata();
|
||||
_registry = new Registry(Defaults);
|
||||
_pipelines = new Pipelines(DefaultBuildPipeline);
|
||||
_registry.Set(typeof(IUnityContainer), null, container);
|
||||
_registry.Set(typeof(IUnityContainerAsync), null, container);
|
||||
_pipelines = new Pipelines(BuildPipeline);
|
||||
_pipelines.Set(typeof(IUnityContainer), null, ResolveContainerPipeline);
|
||||
_pipelines.Set(typeof(IUnityContainerAsync), null, ResolveContainerPipeline);
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Built-In Features
|
||||
|
@ -114,6 +116,7 @@ namespace Unity
|
|||
},
|
||||
new StagedStrategyChain<Pipeline, Stage> // Instance Resolve Pipeline
|
||||
{
|
||||
{ factory, Stage.Factory }
|
||||
});
|
||||
}
|
||||
else
|
||||
|
@ -143,6 +146,7 @@ namespace Unity
|
|||
new StagedStrategyChain<Pipeline, Stage> // Instance Resolve Pipeline
|
||||
{
|
||||
{ diagnostic, Stage.Diagnostic },
|
||||
{ factory, Stage.Factory }
|
||||
});
|
||||
|
||||
// Build process
|
||||
|
|
|
@ -63,11 +63,7 @@ namespace Unity
|
|||
public static TConfigurator Configure<TConfigurator>(this IUnityContainer container)
|
||||
where TConfigurator : IUnityContainerExtensionConfigurator
|
||||
{
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
return (TConfigurator)(container ?? throw new ArgumentNullException(nameof(container))).Configure(typeof(TConfigurator));
|
||||
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
#pragma warning restore CS8603 // Possible null reference return.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
Загрузка…
Ссылка в новой задаче