Adding compiled implementation

This commit is contained in:
Eugene Sadovoi 2019-06-10 23:19:22 -04:00
Родитель a9f7523c48
Коммит 7686fde340
18 изменённых файлов: 399 добавлений и 89 удалений

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

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Unity.Resolution;
@ -7,11 +6,18 @@ namespace Unity
{
public abstract class Pipeline
{
#region Fields
protected static readonly BinaryExpression NullTestExpression = Expression.Equal(Expression.Constant(null), PipelineContextExpression.Existing);
#endregion
#region Public Members
public virtual ResolveDelegate<PipelineContext>? Build(ref PipelineBuilder builder) => builder.Pipeline();
public virtual IEnumerable<Expression> Express(ref PipelineBuilder builder) => Enumerable.Empty<Expression>();
public virtual IEnumerable<Expression> Express(ref PipelineBuilder builder) => builder.Express();
#endregion
}

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

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Security;
using Unity.Exceptions;
using Unity.Injection;
using Unity.Lifetime;
using Unity.Policy;
@ -25,9 +26,6 @@ namespace Unity
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IEnumerator<Pipeline> _enumerator;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IEnumerable<Pipeline> _pipelines;
#endregion
@ -50,9 +48,9 @@ namespace Unity
ContainerContext = container.Context;
Seed = null;
SeedMethod = null;
SeedExpression = null;
_enumerator = pipelines.GetEnumerator();
_pipelines = pipelines;
}
// Pipeline From Registration
@ -72,20 +70,19 @@ namespace Unity
IsMapping = null != registration.Type && type != registration.Type;
BuildRequired = registration.BuildRequired;
Seed = registration.Pipeline;
SeedMethod = registration.Pipeline;
SeedExpression = null;
ContainerContext = registration.Owner.Context;
Debug.Assert(null != registration?.Processors);
_enumerator = registration.Processors.GetEnumerator();
_pipelines = registration.Processors;
}
// Pipeline from factory
public PipelineBuilder(Type type, ExplicitRegistration factory, LifetimeManager manager, UnityContainer owner)
{
Type = type;
Seed = factory.Pipeline;
TypeConverter = factory.BuildType;
LifetimeManager = manager;
InjectionMembers = factory.InjectionMembers;
@ -100,9 +97,11 @@ namespace Unity
ContainerContext = owner.Context;
SeedMethod = factory.Pipeline;
SeedExpression = null;
Debug.Assert(null != factory.Processors);
_enumerator = factory.Processors.GetEnumerator();
_pipelines = factory.Processors;
}
#endregion
@ -131,7 +130,9 @@ namespace Unity
public readonly ContainerContext ContainerContext;
public ResolveDelegate<PipelineContext>? Seed { get; private set; }
public ResolveDelegate<PipelineContext>? SeedMethod { get; private set; }
public IEnumerable<Expression>? SeedExpression { get; private set; }
#endregion
@ -140,37 +141,66 @@ namespace Unity
public ResolveDelegate<PipelineContext> Compile()
{
try
{
ref var context = ref this;
var expressions = _enumerator.MoveNext()
? _enumerator.Current.Express(ref context)
.ToList()
: new List<Expression>();
expressions.Add(PipelineContextExpression.Existing);
var lambda = Expression.Lambda<ResolveDelegate<PipelineContext>>(
Expression.Block(expressions), PipelineContextExpression.Context);
return lambda.Compile();
}
catch (Exception ex)
{
return (ref PipelineContext context) => throw new InvalidRegistrationException(ex.Message);
}
}
public IEnumerable<Expression> Express()
{
ref var context = ref this;
var expressions = _enumerator.MoveNext()
? _enumerator.Current.Express(ref context)
.ToList()
: new List<Expression>();
return _enumerator.MoveNext()
? _enumerator.Current.Express(ref context)
: SeedExpression ?? Enumerable.Empty<Expression>();
}
expressions.Add(PipelineContextExpression.Existing);
public IEnumerable<Expression> Express(ResolveDelegate<PipelineContext> resolver)
{
var expression = Expression.Assign(
PipelineContextExpression.Existing,
Expression.Invoke(Expression.Constant(resolver), PipelineContextExpression.Context));
var lambda = Expression.Lambda<ResolveDelegate<PipelineContext>>(
Expression.Block(expressions), PipelineContextExpression.Context);
SeedExpression = new[] { expression };
return lambda.Compile();
ref var context = ref this;
return _enumerator.MoveNext()
? _enumerator.Current.Express(ref context)
: SeedExpression ?? Enumerable.Empty<Expression>();
}
public ResolveDelegate<PipelineContext>? Pipeline()
{
ref var context = ref this;
return _enumerator.MoveNext()
? _enumerator.Current?.Build(ref context) ?? Seed
: Seed;
? _enumerator.Current?.Build(ref context) ?? SeedMethod
: SeedMethod;
}
public ResolveDelegate<PipelineContext>? Pipeline(ResolveDelegate<PipelineContext>? method = null)
public ResolveDelegate<PipelineContext>? Pipeline(ResolveDelegate<PipelineContext>? method)
{
Seed = method;
SeedMethod = method;
ref var context = ref this;
return _enumerator.MoveNext()
? _enumerator.Current.Build(ref context) ?? Seed
: Seed;
? _enumerator.Current.Build(ref context) ?? SeedMethod
: SeedMethod;
}
#endregion

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

@ -232,33 +232,32 @@ namespace Unity
#region Expression Overrides
// public IEnumerable<Expression> GetExpressions(Type type, ImplicitRegistration registration)
// {
//#if NETSTANDARD1_0 || NETCOREAPP1_0
// var typeInfo = type.GetTypeInfo();
//#else
// var typeInfo = type;
//#endif
// // Validate if Type could be created
// if (typeInfo.IsInterface) return CannotConstructInterfaceExpr;
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
#if NETSTANDARD1_0 || NETCOREAPP1_0
var typeInfo = builder.Type.GetTypeInfo();
#else
var typeInfo = builder.Type;
#endif
// Validate if Type could be created
if (typeInfo.IsInterface) return CannotConstructInterfaceExpr;
// if (typeInfo.IsAbstract) return CannotConstructAbstractClassExpr;
if (typeInfo.IsAbstract) return CannotConstructAbstractClassExpr;
// if (typeInfo.IsSubclassOf(typeof(Delegate)))
// return CannotConstructDelegateExpr;
if (typeInfo.IsSubclassOf(typeof(Delegate)))
return CannotConstructDelegateExpr;
// if (type == typeof(string))
// return TypeIsNotConstructableExpr;
if (typeof(string) == builder.Type)
return TypeIsNotConstructableExpr;
// // Build expression as usual
// return base.GetExpressions(type, registration);
// }
// Build expression as usual
return base.Express(ref builder);
}
protected override Expression GetResolverExpression(ConstructorInfo info, object? resolvers)
protected override IEnumerable<Expression> GetConstructorExpression(ConstructorInfo info, object? resolvers)
{
var ex = Expression.Variable(typeof(Exception));
var exData = Expression.MakeMemberAccess(ex, DataProperty);
var variable = Expression.Variable(info.DeclaringType ?? throw new ArgumentNullException(nameof(info)));
var parameters = info.GetParameters();
// Check if has Out or ByRef parameters
@ -270,11 +269,9 @@ namespace Unity
info.DeclaringType, info))))
// Create new instance
: Expression.Block(new[] { variable }, new Expression[]
{
Expression.Assign(variable, Expression.New(info, CreateDiagnosticParameterExpressions(info.GetParameters(), resolvers))),
Expression.Assign(PipelineContextExpression.Existing, Expression.Convert(variable, typeof(object)))
});
: Expression.Assign(
PipelineContextExpression.Existing,
Expression.Convert(Expression.New(info, CreateDiagnosticParameterExpressions(info.GetParameters(), resolvers)), typeof(object)));
// Add location to dictionary and re-throw
var catchBlock = Expression.Block(tryBlock.Type,
@ -284,14 +281,14 @@ namespace Unity
Expression.Rethrow(tryBlock.Type));
// Create
return Expression.IfThen(Expression.Equal(Expression.Constant(null), PipelineContextExpression.Existing),
yield return Expression.IfThen(Expression.Equal(Expression.Constant(null), PipelineContextExpression.Existing),
Expression.TryCatch(tryBlock, Expression.Catch(ex, catchBlock)));
// Report error
string CreateErrorMessage(string format, Type type, MethodBase constructor)
{
var parameterDescriptions =
constructor.GetParameters()
.Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}");
.Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}");
return string.Format(format, type.FullName, string.Join(", ", parameterDescriptions));
}
@ -304,7 +301,7 @@ namespace Unity
public override ResolveDelegate<PipelineContext>? Build(ref PipelineBuilder builder)
{
if (null != builder.Seed) return builder.Pipeline();
if (null != builder.SeedMethod) return builder.Pipeline();
var type = builder.Type;

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

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Unity.Injection;
using Unity.Lifetime;
namespace Unity
@ -20,32 +22,79 @@ namespace Unity
Expression.New(PerResolveInfo, PipelineContextExpression.Existing));
protected static readonly Expression[] NoConstructorExpr = new [] {
Expression.IfThen(Expression.Equal(Expression.Constant(null), PipelineContextExpression.Existing),
Expression.IfThen(NullTestExpression,
Expression.Throw(
Expression.New(InvalidRegistrationExpressionCtor,
Expression.Call(StringFormat,
Expression.Constant("No public constructor is available for type {0}."),
PipelineContextExpression.Type))))};
public object BuilderContextExpression { get; private set; }
#endregion
#region PipelineBuilder
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
var expressions = builder.Express();
if (null != builder.SeedExpression) return expressions;
// Select ConstructorInfo
var selector = GetOrDefault(builder.Policies);
var selection = selector.Invoke(builder.Type, builder.InjectionMembers)
.FirstOrDefault();
// Select constructor for the Type
ConstructorInfo info;
object[]? resolvers = null;
switch (selection)
{
case ConstructorInfo memberInfo:
info = memberInfo;
break;
case MethodBase<ConstructorInfo> injectionMember:
info = injectionMember.MemberInfo(builder.Type);
resolvers = injectionMember.Data;
break;
case Exception exception:
return new[] {Expression.IfThen(
Expression.Equal(Expression.Constant(null), PipelineContextExpression.Existing),
Expression.Throw(Expression.Constant(exception)))};
default:
return NoConstructorExpr;
}
// Get lifetime manager
var lifetimeManager = (LifetimeManager?)builder.Policies?.Get(typeof(LifetimeManager));
return lifetimeManager is PerResolveLifetimeManager
? GetConstructorExpression(info, resolvers).Concat(new[] { SetPerBuildSingletonExpr })
.Concat(expressions)
: GetConstructorExpression(info, resolvers).Concat(expressions);
}
#endregion
#region Overrides
protected override Expression GetResolverExpression(ConstructorInfo info, object? resolvers)
protected virtual IEnumerable<Expression> GetConstructorExpression(ConstructorInfo info, object? resolvers)
{
var variable = Expression.Variable(info.DeclaringType);
var parametersExpr = CreateParameterExpressions(info.GetParameters(), resolvers);
return Expression.IfThen(
Expression.Equal(Expression.Constant(null), PipelineContextExpression.Existing),
Expression.Block(new[] { variable }, new Expression[]
{
Expression.Assign(variable, Expression.New(info, parametersExpr)),
Expression.Assign(PipelineContextExpression.Existing, Expression.Convert(variable, typeof(object)))
}));
yield return Expression.IfThen(NullTestExpression,
Expression.Assign(PipelineContextExpression.Existing,
Expression.Convert(Expression.New(info, parametersExpr), typeof(object))));
}
#endregion
}
}

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

@ -12,12 +12,11 @@ namespace Unity
{
#region PipelineBuilder
public override ResolveDelegate<PipelineContext>? Build(ref PipelineBuilder builder)
{
var pipeline = builder.Pipeline();
if (null != builder.Seed) return pipeline;
if (null != builder.SeedMethod) return pipeline;
// Verify if can build
#if NETSTANDARD1_0 || NETCOREAPP1_0

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

@ -44,6 +44,11 @@ namespace Unity
.GetDeclaredMethods(nameof(PipelineContext.Set))
.First(m => 2 == m.GetParameters().Length);
public static readonly MethodInfo GetMethod =
typeof(PipelineContext).GetTypeInfo()
.GetDeclaredMethods(nameof(PipelineContext.Get))
.First(m => 1 == m.GetParameters().Length);
#endregion

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

@ -1,7 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using System.Security;
using Unity;
using Unity.Exceptions;
using Unity.Resolution;

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

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
using Unity;
using Unity.Exceptions;
using Unity.Factories;
using Unity.Policy;
using Unity.Resolution;
namespace Unity
{
public partial class FactoryPipeline : Pipeline
{
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
// Skip if already have a resolver expression
if (null != builder.SeedExpression) return builder.Express();
// Try to get resolver
Type? generic = null;
var resolver = builder.Policies?.Get(typeof(ResolveDelegate<PipelineContext>)) ??
builder.ContainerContext.Get(builder.Type, typeof(ResolveDelegate<PipelineContext>));
if (null == resolver)
{
#if NETCOREAPP1_0 || NETSTANDARD1_0
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
#else
if (null != builder.Type && builder.Type.IsGenericType)
#endif
{
generic = builder.Type.GetGenericTypeDefinition();
resolver = builder.ContainerContext.Get(generic, typeof(ResolveDelegate<PipelineContext>));
}
}
// Create an expression from resolver
if (null != resolver) return builder.Express((ResolveDelegate<PipelineContext>)resolver);
// Try finding factory
TypeFactoryDelegate? factory = builder.Policies?.Get<TypeFactoryDelegate>();
#if NETCOREAPP1_0 || NETSTANDARD1_0
if (null != builder.Type && builder.Type.GetTypeInfo().IsGenericType)
#else
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.Express((ref PipelineContext context) => resolve(ref context));
}
else
{
var message = $"Invalid array {builder.Type}. Only arrays of rank 1 are supported";
return builder.Express((ref PipelineContext context) => throw new InvalidRegistrationException(message));
}
}
Debug.Assert(null != builder.Type);
return null != factory
? builder.Express(factory(builder.Type, builder.ContainerContext.Container))
: builder.Express();
}
}
}

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

@ -1,7 +1,6 @@
using System;
using System.Diagnostics;
using System.Reflection;
using Unity;
using Unity.Exceptions;
using Unity.Factories;
using Unity.Policy;
@ -9,14 +8,12 @@ using Unity.Resolution;
namespace Unity
{
public class FactoryPipeline : Pipeline
public partial class FactoryPipeline : Pipeline
{
#region PipelineBuilder
public override ResolveDelegate<PipelineContext>? Build(ref PipelineBuilder builder)
{
// Skip if already have a resolver
if (null != builder.Seed) return builder.Pipeline();
if (null != builder.SeedMethod) return builder.Pipeline();
// Try to get resolver
Type? generic = null;
@ -71,7 +68,5 @@ namespace Unity
? builder.Pipeline(factory(builder.Type, builder.ContainerContext.Container))
: builder.Pipeline();
}
#endregion
}
}

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

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using Unity;
using Unity.Exceptions;
using Unity.Injection;
using Unity.Resolution;

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

@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Unity.Lifetime;
namespace Unity
{
public partial class LifetimePipeline : Pipeline
{
#region Fields
private static readonly MethodInfo _recoverMethod = typeof(SynchronizedLifetimeManager)
.GetTypeInfo().GetDeclaredMethod(nameof(SynchronizedLifetimeManager.Recover));
private static readonly ConstructorInfo _perResolveInfo = typeof(RuntimePerResolveLifetimeManager)
.GetTypeInfo().DeclaredConstructors.First();
protected static readonly Expression SetPerBuildSingletonExpr =
Expression.Call(PipelineContextExpression.Context,
PipelineContextExpression.SetMethod,
Expression.Constant(typeof(LifetimeManager), typeof(Type)),
Expression.New(_perResolveInfo, PipelineContextExpression.Existing));
#endregion
#region PipelineBuilder
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
var expressions = builder.Express();
return builder.LifetimeManager switch
{
SynchronizedLifetimeManager manager => SynchronizedLifetimeExpression(manager, expressions),
PerResolveLifetimeManager _ => PerResolveLifetimeExpression(expressions),
_ => expressions
};
}
#endregion
#region Implementation
protected virtual IEnumerable<Expression> SynchronizedLifetimeExpression(SynchronizedLifetimeManager manager, IEnumerable<Expression> expressions)
{
var tryBody = Expression.Block(expressions);
var catchBody = Expression.Catch(typeof(Exception), Expression.Block(
Expression.Call(Expression.Constant(manager), _recoverMethod),
Expression.Rethrow(tryBody.Type)));
yield return Expression.TryCatch(tryBody, catchBody);
}
protected virtual IEnumerable<Expression> PerResolveLifetimeExpression(IEnumerable<Expression> expressions)
{
Expression exp;
try
{
ParameterExpression _valueExpr = Expression.Variable(typeof(object));
ParameterExpression _lifetimeExpr = Expression.Variable(typeof(LifetimeManager));
MethodCallExpression _getManagerExpr = Expression.Call(
PipelineContextExpression.Context,
PipelineContextExpression.GetMethod,
Expression.Constant(typeof(LifetimeManager), typeof(Type)));
exp = Expression.IfThenElse(NullTestExpression,
Expression.Block(new[] { _lifetimeExpr, _valueExpr }, new Expression[]
{
Expression.Assign(_lifetimeExpr, Expression.Convert(_getManagerExpr, typeof(LifetimeManager))),
//Expression.IfThen(
// Expression.NotEqual(Expression.Constant(null), _lifetimeExpr),
// Expression.Assign()),
Expression.Block(expressions)
}),
Expression.Block(expressions));
}
catch (Exception ex)
{
throw;
}
yield return exp;
}
#endregion
}
}

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

@ -4,7 +4,7 @@ using Unity.Resolution;
namespace Unity
{
public class LifetimePipeline : Pipeline
public partial class LifetimePipeline : Pipeline
{
#region PipelineBuilder
@ -15,15 +15,18 @@ namespace Unity
return builder.LifetimeManager switch
{
SynchronizedLifetimeManager manager => SynchronizedLifetime(manager, pipeline),
PerResolveLifetimeManager _ => PerResolveLifetime(pipeline),
SynchronizedLifetimeManager manager => SynchronizedLifetimeResolution(manager, pipeline),
PerResolveLifetimeManager _ => PerResolveLifetimeResolution(pipeline),
_ => pipeline
};
}
#endregion
private ResolveDelegate<PipelineContext> SynchronizedLifetime(SynchronizedLifetimeManager manager, ResolveDelegate<PipelineContext> pipeline)
#region Implementation
protected virtual ResolveDelegate<PipelineContext> SynchronizedLifetimeResolution(SynchronizedLifetimeManager manager, ResolveDelegate<PipelineContext> pipeline)
{
return (ref PipelineContext context) =>
{
@ -40,14 +43,14 @@ namespace Unity
};
}
private ResolveDelegate<PipelineContext> PerResolveLifetime(ResolveDelegate<PipelineContext> pipeline)
protected virtual ResolveDelegate<PipelineContext> PerResolveLifetimeResolution(ResolveDelegate<PipelineContext> pipeline)
{
return (ref PipelineContext context) =>
{
object? value;
LifetimeManager? lifetime;
object? value;
LifetimeManager? lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager));
if (null != (lifetime = (LifetimeManager?)context.Get(typeof(LifetimeManager))))
if (null != lifetime)
{
value = lifetime.Get(context.ContainerContext.Lifetime);
if (LifetimeManager.NoValue != value) return value;
@ -61,5 +64,7 @@ namespace Unity
return value;
};
}
#endregion
}
}

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

@ -0,0 +1,39 @@
using System.Collections.Generic;
using System.Linq.Expressions;
namespace Unity
{
public partial class MappingPipeline : Pipeline
{
#region PipelineBuilder
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
if (!builder.IsMapping) return builder.Express();
var requestedType = builder.Type;
if (null != builder.Registration)
{
// Explicit Registration
if (null == builder.Registration.Type) return builder.Express();
builder.Type = builder.Registration.Type;
}
else if (null != builder.TypeConverter)
{
builder.Type = builder.TypeConverter(builder.Type);
}
// If nothing to map or build required, just create it
if (builder.BuildRequired || requestedType == builder.Type)
return builder.Express();
var type = builder.Type;
return builder.Express((ref PipelineContext context) => context.Resolve(type));
}
#endregion
}
}

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

@ -1,9 +1,8 @@
using Unity;
using Unity.Resolution;
using Unity.Resolution;
namespace Unity
{
public class MappingPipeline : Pipeline
public partial class MappingPipeline : Pipeline
{
#region PipelineBuilder

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

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Unity.Injection;
@ -8,6 +9,23 @@ namespace Unity
{
public abstract partial class MemberPipeline<TMemberInfo, TData> where TMemberInfo : MemberInfo
{
#region PipelineBuilder
public override IEnumerable<Expression> Express(ref PipelineBuilder builder)
{
if (null != builder.SeedExpression) return builder.Express();
var expressions = builder.Express();
var selector = GetOrDefault(builder.Policies);
var members = selector.Invoke(builder.Type, builder.InjectionMembers);
return expressions.Concat(ExpressionsFromSelection(builder.Type, members));
}
#endregion
#region Selection Processing
protected virtual IEnumerable<Expression> ExpressionsFromSelection(Type type, IEnumerable<object> members)
@ -52,7 +70,7 @@ namespace Unity
#region Implementation
protected abstract Expression GetResolverExpression(TMemberInfo info, object? resolver);
protected virtual Expression GetResolverExpression(TMemberInfo info, object? resolver) => throw new NotImplementedException();
#endregion
}

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

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Unity;
using Unity.Exceptions;
using Unity.Injection;
using Unity.Resolution;
@ -16,7 +15,7 @@ namespace Unity
public override ResolveDelegate<PipelineContext>? Build(ref PipelineBuilder builder)
{
if (null != builder.Seed) return builder.Pipeline();
if (null != builder.SeedMethod) return builder.Pipeline();
var pipeline = builder.Pipeline();
var selector = GetOrDefault(builder.Policies);

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

@ -146,7 +146,8 @@ namespace Unity
if ((Delegate)(ResolveDelegate<PipelineContext>)SpinWait == manager.PipelineDelegate)
{
PipelineBuilder builder = new PipelineBuilder(type, registration);
manager.PipelineDelegate = builder.Pipeline();
// manager.PipelineDelegate = builder.Pipeline();
manager.PipelineDelegate = builder.Compile();
Debug.Assert(null != manager.PipelineDelegate);
pipeline = (ResolveDelegate<PipelineContext>)manager.PipelineDelegate;
}

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

@ -277,6 +277,7 @@ namespace Unity
{
PipelineBuilder builder = new PipelineBuilder(key.Type, this, Context.TypePipelineCache);
manager.PipelineDelegate = builder.Pipeline();
// manager.PipelineDelegate = builder.Compile();
Debug.Assert(null != manager.PipelineDelegate);
pipeline = (ResolveDelegate<PipelineContext>)manager.PipelineDelegate;
}