Adding compiled implementation
This commit is contained in:
Родитель
a9f7523c48
Коммит
7686fde340
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче