Restore point
This commit is contained in:
Родитель
896c609849
Коммит
9dd0e2a620
|
@ -9,6 +9,7 @@ using Unity.Lifetime;
|
|||
using Unity.Policy;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
using static Unity.UnityContainer;
|
||||
|
||||
namespace Unity.Builder
|
||||
|
@ -159,89 +160,7 @@ namespace Unity.Builder
|
|||
#endregion
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public object? Resolve(Type type)
|
||||
{
|
||||
// Process overrides if any
|
||||
if (0 < Overrides.Length)
|
||||
{
|
||||
NamedType namedType = new NamedType
|
||||
{
|
||||
Type = type,
|
||||
Name = Name
|
||||
};
|
||||
|
||||
// Check if this parameter is overridden
|
||||
for (var index = Overrides.Length - 1; index >= 0; --index)
|
||||
{
|
||||
var resolverOverride = Overrides[index];
|
||||
// If matches with current parameter
|
||||
if (resolverOverride is IResolve resolverPolicy &&
|
||||
resolverOverride is IEquatable<NamedType> comparer && comparer.Equals(namedType))
|
||||
{
|
||||
var context = this;
|
||||
|
||||
return DependencyResolvePipeline(ref context, resolverPolicy.Resolve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Resolve(type, ((UnityContainer)Container).GetRegistration(type, Name));
|
||||
}
|
||||
|
||||
public object? Resolve(Type type, IRegistration registration)
|
||||
{
|
||||
if (ReferenceEquals(Registration, registration)) throw new CircularDependencyException(type, registration.Name);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var thisContext = this;
|
||||
var context = new BuilderContext
|
||||
{
|
||||
ContainerContext = ContainerContext,
|
||||
Registration = registration,
|
||||
IsAsync = IsAsync,
|
||||
Type = type,
|
||||
List = List,
|
||||
Overrides = Overrides,
|
||||
DeclaringType = Type,
|
||||
#if !NET40
|
||||
Parent = new IntPtr(Unsafe.AsPointer(ref thisContext))
|
||||
#endif
|
||||
};
|
||||
|
||||
var manager = registration.LifetimeManager switch
|
||||
{
|
||||
null => TransientLifetimeManager.Instance,
|
||||
PerResolveLifetimeManager _ => (LifetimeManager?)context.Get(typeof(LifetimeManager)) ??
|
||||
TransientLifetimeManager.Instance,
|
||||
_ => registration.LifetimeManager
|
||||
};
|
||||
|
||||
// Check if already got value
|
||||
var value = manager.GetValue(ContainerContext.Lifetime);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
if (registration.LifetimeManager is SynchronizedLifetimeManager synchronized)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = context.Pipeline(ref context);
|
||||
}
|
||||
catch
|
||||
{
|
||||
synchronized.Recover();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
value = context.Pipeline(ref context);
|
||||
|
||||
manager.SetValue(value, ContainerContext.Lifetime);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
#region Member Resolution
|
||||
|
||||
public object? Resolve(ParameterInfo parameter, object? value)
|
||||
{
|
||||
|
@ -397,5 +316,126 @@ namespace Unity.Builder
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public object? Resolve(Type type)
|
||||
{
|
||||
// Process overrides if any
|
||||
if (0 < Overrides.Length)
|
||||
{
|
||||
NamedType namedType = new NamedType
|
||||
{
|
||||
Type = type,
|
||||
Name = Name
|
||||
};
|
||||
|
||||
// Check if this parameter is overridden
|
||||
for (var index = Overrides.Length - 1; index >= 0; --index)
|
||||
{
|
||||
var resolverOverride = Overrides[index];
|
||||
// If matches with current parameter
|
||||
if (resolverOverride is IResolve resolverPolicy &&
|
||||
resolverOverride is IEquatable<NamedType> comparer && comparer.Equals(namedType))
|
||||
{
|
||||
var context = this;
|
||||
|
||||
return DependencyResolvePipeline(ref context, resolverPolicy.Resolve);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var key = new HashKey(type, Name);
|
||||
return Resolve(ContainerContext.Container.GetPipeline(ref key));
|
||||
}
|
||||
|
||||
public object? Resolve(Type type, IRegistration registration)
|
||||
{
|
||||
if (ReferenceEquals(Registration, registration)) throw new CircularDependencyException(type, registration.Name);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var thisContext = this;
|
||||
var container = registration.LifetimeManager is ContainerControlledLifetimeManager containerControlled
|
||||
? (ContainerContext)containerControlled.Scope
|
||||
: ContainerContext;
|
||||
|
||||
var context = new BuilderContext
|
||||
{
|
||||
ContainerContext = container,
|
||||
Registration = registration,
|
||||
IsAsync = IsAsync,
|
||||
Type = type,
|
||||
List = List,
|
||||
Overrides = Overrides,
|
||||
DeclaringType = Type,
|
||||
#if !NET40
|
||||
Parent = new IntPtr(Unsafe.AsPointer(ref thisContext))
|
||||
#endif
|
||||
};
|
||||
|
||||
var manager = registration.LifetimeManager switch
|
||||
{
|
||||
null => TransientLifetimeManager.Instance,
|
||||
PerResolveLifetimeManager _ => (LifetimeManager?)context.Get(typeof(LifetimeManager)) ??
|
||||
TransientLifetimeManager.Instance,
|
||||
_ => registration.LifetimeManager
|
||||
};
|
||||
|
||||
// Check if already got value
|
||||
var value = manager.GetValue(ContainerContext.Lifetime);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
|
||||
if (registration.LifetimeManager is SynchronizedLifetimeManager synchronized)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = context.Pipeline(ref context);
|
||||
}
|
||||
catch
|
||||
{
|
||||
synchronized.Recover();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
value = context.Pipeline(ref context);
|
||||
|
||||
manager.SetValue(value, ContainerContext.Lifetime);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public object? Resolve(ResolveDelegate<BuilderContext> pipeline)
|
||||
{
|
||||
// Check if already created and acquire a lock if not
|
||||
var manager = pipeline.Target as LifetimeManager;
|
||||
if (null != manager)
|
||||
{
|
||||
// Make blocking check for result
|
||||
var value = manager.Get(ContainerContext.Lifetime);
|
||||
if (LifetimeManager.NoValue != value) return value;
|
||||
}
|
||||
|
||||
// Setup Context
|
||||
var synchronized = manager as SynchronizedLifetimeManager;
|
||||
var thisContext = this;
|
||||
|
||||
try
|
||||
{
|
||||
// Execute pipeline
|
||||
var value = pipeline(ref thisContext);
|
||||
manager?.Set(value, ContainerContext.Lifetime);
|
||||
return value;
|
||||
}
|
||||
catch when (null != synchronized)
|
||||
{
|
||||
synchronized.Recover();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,13 +34,17 @@ namespace Unity
|
|||
public PipelineBuilder(Type type, UnityContainer container, IEnumerable<Pipeline> pipelines)
|
||||
{
|
||||
Type = type;
|
||||
BuildType = null;
|
||||
TypeConverter = null;
|
||||
BuildRequired = false;
|
||||
LifetimeManager = null;
|
||||
InjectionMembers = null;
|
||||
|
||||
Factory = null;
|
||||
Policies = null;
|
||||
Registration = null;
|
||||
|
||||
IsMapping = false;
|
||||
BuildRequired = false;
|
||||
|
||||
ContainerContext = container.Context;
|
||||
|
||||
Seed = null;
|
||||
|
@ -48,18 +52,22 @@ namespace Unity
|
|||
}
|
||||
|
||||
// Pipeline From Registration
|
||||
public PipelineBuilder(ExplicitRegistration registration)
|
||||
public PipelineBuilder(Type type, ExplicitRegistration registration)
|
||||
{
|
||||
Debug.Assert(null != registration.Type);
|
||||
|
||||
Type = registration.Type;
|
||||
BuildType = null;
|
||||
Type = type;
|
||||
TypeConverter = null;
|
||||
BuildRequired = registration.BuildRequired;
|
||||
LifetimeManager = registration.LifetimeManager;
|
||||
InjectionMembers = registration.InjectionMembers;
|
||||
|
||||
Factory = null;
|
||||
Policies = registration;
|
||||
Registration = registration;
|
||||
|
||||
IsMapping = null != registration.Type && type != registration.Type;
|
||||
BuildRequired = registration.BuildRequired;
|
||||
|
||||
Seed = registration.Pipeline;
|
||||
|
||||
ContainerContext = registration.Owner.Context;
|
||||
|
@ -71,14 +79,19 @@ namespace Unity
|
|||
// Pipeline from context
|
||||
public PipelineBuilder(ref BuilderContext context)
|
||||
{
|
||||
var type = (context.Registration as ExplicitRegistration)?.Type ?? context.Type;
|
||||
Type = context.Type;
|
||||
BuildType = (context.Registration as ExplicitRegistration)?.Type;
|
||||
TypeConverter = context.Registration?.BuildType;
|
||||
BuildRequired = context.Registration?.BuildRequired ?? false;
|
||||
LifetimeManager = context.Registration?.LifetimeManager;
|
||||
InjectionMembers = context.Registration?.InjectionMembers;
|
||||
|
||||
Policies = context.Registration;
|
||||
Registration = context.Registration as ExplicitRegistration;
|
||||
Factory = null != Registration ? null : context.Registration as ImplicitRegistration;
|
||||
Policies = Registration ?? Factory;
|
||||
|
||||
IsMapping = (null != Registration?.Type && Registration?.Type != Type) || null != Factory?.BuildType;
|
||||
BuildRequired = context.Registration?.BuildRequired ?? false;
|
||||
|
||||
ContainerContext = context.ContainerContext;
|
||||
|
||||
Seed = context.Registration?.Pipeline;
|
||||
|
@ -91,15 +104,18 @@ namespace Unity
|
|||
public PipelineBuilder(Type type, ExplicitRegistration factory, UnityContainer owner)
|
||||
{
|
||||
Type = type;
|
||||
BuildType = factory.Type;
|
||||
Seed = factory.Pipeline;
|
||||
TypeConverter = factory.BuildType;
|
||||
// TODO: Move to registration
|
||||
BuildRequired = null != factory.InjectionMembers && factory.InjectionMembers.Any(m => m.BuildRequired);
|
||||
LifetimeManager = factory.LifetimeManager?.CreateLifetimePolicy();
|
||||
InjectionMembers = factory.InjectionMembers;
|
||||
|
||||
Policies = null;
|
||||
Factory = factory;
|
||||
Policies = factory;
|
||||
Registration = null;
|
||||
|
||||
IsMapping = null != factory.BuildType;
|
||||
// TODO: Move to registration
|
||||
BuildRequired = null != factory.InjectionMembers && factory.InjectionMembers.Any(m => m.BuildRequired);
|
||||
|
||||
ContainerContext = owner.Context;
|
||||
|
||||
|
@ -114,12 +130,17 @@ namespace Unity
|
|||
|
||||
public Type Type;
|
||||
|
||||
public readonly Type? BuildType;
|
||||
|
||||
public LifetimeManager? LifetimeManager { get; }
|
||||
|
||||
public InjectionMember[]? InjectionMembers { get; set; }
|
||||
|
||||
public ExplicitRegistration? Registration { get; }
|
||||
|
||||
public ImplicitRegistration? Factory { get; }
|
||||
|
||||
|
||||
public bool IsMapping { get; }
|
||||
|
||||
public bool BuildRequired { get; }
|
||||
|
||||
public Converter<Type, Type>? TypeConverter { get; }
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
using System.Diagnostics;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Resolution;
|
||||
using static Unity.UnityContainer;
|
||||
|
||||
namespace Unity
|
||||
{
|
||||
public class LifetimePipeline : Pipeline
|
||||
{
|
||||
#region PipelineBuilder
|
||||
|
||||
public override ResolveDelegate<BuilderContext>? Build(ref PipelineBuilder builder)
|
||||
{
|
||||
if (builder.LifetimeManager is ContainerControlledLifetimeManager manager)
|
||||
{
|
||||
var pipeline = builder.Pipeline();
|
||||
Debug.Assert(null != pipeline);
|
||||
|
||||
return (ref BuilderContext context) =>
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return builder.Pipeline(); ;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using Unity.Builder;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
|
||||
namespace Unity
|
||||
|
@ -10,16 +9,16 @@ namespace Unity
|
|||
|
||||
public override ResolveDelegate<BuilderContext>? Build(ref PipelineBuilder builder)
|
||||
{
|
||||
if (!builder.IsMapping) return builder.Pipeline();
|
||||
|
||||
var requestedType = builder.Type;
|
||||
|
||||
if (builder.Policies is ExplicitRegistration @explicit)
|
||||
if (null != builder.Registration)
|
||||
{
|
||||
// Explicit Registration
|
||||
if (null == @explicit.Type) return builder.Pipeline();
|
||||
if (null == builder.Registration.Type) return builder.Pipeline();
|
||||
|
||||
builder.Type = (null == @explicit.BuildType)
|
||||
? @explicit.Type
|
||||
: @explicit.BuildType(@explicit.Type);
|
||||
builder.Type = builder.Registration.Type;
|
||||
}
|
||||
else if (null != builder.TypeConverter)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace Unity.Registration
|
|||
LifetimeManager = lifetimeManager;
|
||||
InjectionMembers = null;
|
||||
BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired);
|
||||
|
||||
if (lifetimeManager is ContainerControlledLifetimeManager manager)
|
||||
manager.Scope = owner.Context;
|
||||
}
|
||||
|
||||
public ExplicitRegistration(UnityContainer owner, string? name, Type? type, LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
|
||||
|
@ -42,6 +45,9 @@ namespace Unity.Registration
|
|||
InjectionMembers = null != injectionMembers && 0 < injectionMembers.Length ? injectionMembers : null;
|
||||
BuildRequired = null != InjectionMembers && InjectionMembers.Any(m => m.BuildRequired) || lifetimeManager is PerResolveLifetimeManager;
|
||||
BuildType = GetTypeConverter();
|
||||
|
||||
if (lifetimeManager is ContainerControlledLifetimeManager manager)
|
||||
manager.Scope = owner.Context;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -202,7 +202,6 @@ namespace Unity
|
|||
|
||||
#region Getting objects
|
||||
|
||||
/*
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
object? IUnityContainer.Resolve(Type type, string? name, params ResolverOverride[] overrides)
|
||||
|
@ -250,7 +249,7 @@ namespace Unity
|
|||
else throw;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
/// <inheritdoc />
|
||||
[SecuritySafeCritical]
|
||||
object? IUnityContainer.Resolve(Type type, string? name, params ResolverOverride[] overrides)
|
||||
|
@ -296,6 +295,7 @@ namespace Unity
|
|||
else throw;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace Unity
|
|||
return null;
|
||||
}
|
||||
|
||||
private ResolveDelegate<BuilderContext> GetPipeline(ref HashKey key)
|
||||
internal ResolveDelegate<BuilderContext> GetPipeline(ref HashKey key)
|
||||
{
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
var info = key.Type?.GetTypeInfo();
|
||||
|
@ -268,6 +268,12 @@ namespace Unity
|
|||
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)
|
||||
|
@ -277,7 +283,7 @@ namespace Unity
|
|||
{
|
||||
if (null != pipeline) return pipeline(ref context);
|
||||
|
||||
PipelineBuilder builder = new PipelineBuilder(registration);
|
||||
PipelineBuilder builder = new PipelineBuilder(type, registration);
|
||||
|
||||
if (registration.LifetimeManager is LifetimeManager manager)
|
||||
{
|
||||
|
@ -324,6 +330,18 @@ namespace Unity
|
|||
int position = 0;
|
||||
var collisions = 0;
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
ResolveDelegate<BuilderContext> buildPipeline = null;
|
||||
|
||||
if (null != factory.LifetimeManager && !(factory.LifetimeManager is TransientLifetimeManager))
|
||||
{
|
||||
var manager = factory.LifetimeManager.CreateLifetimePolicy();
|
||||
if (manager is ContainerControlledLifetimeManager containerControlled) containerControlled.Scope = this;
|
||||
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)BuildPipeline;
|
||||
buildPipeline = manager.Pipeline;
|
||||
}
|
||||
else
|
||||
buildPipeline = BuildPipeline;
|
||||
|
||||
// Add Pipeline to the Registry
|
||||
lock (_syncLock)
|
||||
|
@ -355,14 +373,14 @@ namespace Unity
|
|||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.Key = key;
|
||||
entry.Type = type;
|
||||
entry.Pipeline = BuildPipeline;
|
||||
entry.Pipeline = buildPipeline;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
position = _registry.Count++;
|
||||
_registry.Buckets[targetBucket] = position;
|
||||
}
|
||||
|
||||
// Return temporary pipeline
|
||||
return BuildPipeline;
|
||||
return buildPipeline;
|
||||
|
||||
|
||||
// Create pipeline and add to Registry
|
||||
|
|
|
@ -90,6 +90,7 @@ namespace Unity
|
|||
// Pipelines
|
||||
|
||||
var factory = new FactoryPipeline();
|
||||
var lifetime = new LifetimePipeline();
|
||||
|
||||
// Mode of operation
|
||||
if (ExecutionMode.IsOptimized())
|
||||
|
@ -102,6 +103,7 @@ namespace Unity
|
|||
Context = new ContainerContext(this,
|
||||
new StagedStrategyChain<Pipeline, Stage> // Type Build Pipeline
|
||||
{
|
||||
{ lifetime, Stage.Lifetime },
|
||||
{ factory, Stage.Factory },
|
||||
{ new MappingPipeline(), Stage.TypeMapping },
|
||||
{ new ConstructorPipeline(this), Stage.Creation },
|
||||
|
@ -111,6 +113,7 @@ namespace Unity
|
|||
},
|
||||
new StagedStrategyChain<Pipeline, Stage> // Factory Resolve Pipeline
|
||||
{
|
||||
{ lifetime, Stage.Lifetime },
|
||||
{ factory, Stage.Factory }
|
||||
},
|
||||
new StagedStrategyChain<Pipeline, Stage> // Instance Resolve Pipeline
|
||||
|
|
|
@ -359,6 +359,7 @@ namespace Unity
|
|||
registration.Processors = Context.TypePipelineCache;
|
||||
|
||||
if (registration.LifetimeManager is IDisposable) LifetimeContainer.Add(registration.LifetimeManager);
|
||||
if (registration.LifetimeManager is ContainerControlledLifetimeManager manager) manager.Scope = this.Context;
|
||||
|
||||
return registration;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче