ExpressionExtensions
Holds the Expression extension methods.
using Stashbox;
using Stashbox.Configuration;
using Stashbox.Expressions.Compile;
using Stashbox.Registration;
using Stashbox.Resolution;
using Stashbox.Utils;
using Stashbox.Utils.Data;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace System.Linq.Expressions
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public static class ExpressionExtensions
{
private static Expression PostProcess(this Expression expression)
{
if (expression.NodeType == ExpressionType.Convert) {
UnaryExpression unaryExpression = expression as UnaryExpression;
if (unaryExpression != null && unaryExpression.Operand.Type == TypeCache<object>.Type)
return unaryExpression;
}
if (!expression.Type.IsValueType)
return expression;
return expression.ConvertTo(TypeCache<object>.Type);
}
public static Func<IResolutionScope, IRequestContext, object> CompileDelegate(this Expression expression, ResolutionContext resolutionContext, ContainerConfiguration containerConfiguration)
{
expression = expression.PostProcess();
ConstantExpression constantExpression = expression as ConstantExpression;
if (constantExpression != null && constantExpression.Value != null) {
object instance = constantExpression.Value;
return (IResolutionScope _, IRequestContext _) => instance;
}
if (!resolutionContext.DefinedVariables.IsEmpty) {
resolutionContext.SingleInstructions.Add(expression);
expression = resolutionContext.SingleInstructions.AsBlock(resolutionContext.DefinedVariables.Walk());
}
if (containerConfiguration.ExternalExpressionCompiler != null)
return (Func<IResolutionScope, IRequestContext, object>)containerConfiguration.ExternalExpressionCompiler(expression.AsLambda(resolutionContext.CurrentScopeParameter, resolutionContext.RequestContextParameter));
Delegate resultDelegate = default(Delegate);
if (!expression.TryEmit(out resultDelegate, TypeCache<Func<IResolutionScope, IRequestContext, object>>.Type, TypeCache<object>.Type, resolutionContext.CurrentScopeParameter, resolutionContext.RequestContextParameter))
resultDelegate = expression.AsLambda(resolutionContext.CurrentScopeParameter, resolutionContext.RequestContextParameter).Compile();
return (Func<IResolutionScope, IRequestContext, object>)resultDelegate;
}
public static Delegate CompileDelegate(this LambdaExpression expression)
{
if (!expression.TryEmit(out Delegate resultDelegate))
throw new InvalidOperationException("Could not compile the given expression!");
return resultDelegate;
}
public static Func<IResolutionScope, IRequestContext, Delegate> CompileDynamicDelegate(this Expression expression, ResolutionContext resolutionContext, ContainerConfiguration containerConfiguration)
{
expression = expression.PostProcess();
if (!resolutionContext.DefinedVariables.IsEmpty) {
resolutionContext.SingleInstructions.Add(expression);
expression = resolutionContext.SingleInstructions.AsBlock(resolutionContext.DefinedVariables.Walk());
}
if (containerConfiguration.ExternalExpressionCompiler != null)
return (Func<IResolutionScope, IRequestContext, Delegate>)containerConfiguration.ExternalExpressionCompiler(expression.AsLambda(resolutionContext.CurrentScopeParameter, resolutionContext.RequestContextParameter));
Delegate resultDelegate = default(Delegate);
if (!expression.TryEmit(out resultDelegate, TypeCache<Func<IResolutionScope, IRequestContext, Delegate>>.Type, TypeCache<Delegate>.Type, resolutionContext.CurrentScopeParameter, resolutionContext.RequestContextParameter))
resultDelegate = expression.AsLambda<Func<IResolutionScope, IRequestContext, Delegate>>(new ParameterExpression[2] {
resolutionContext.CurrentScopeParameter,
resolutionContext.RequestContextParameter
}).Compile();
return (Func<IResolutionScope, IRequestContext, Delegate>)resultDelegate;
}
[System.Runtime.CompilerServices.NullableContext(2)]
public static ServiceContext AsServiceContext(this Expression expression, ServiceRegistration serviceRegistration = null)
{
if (expression != null)
return new ServiceContext(expression, serviceRegistration);
return ServiceContext.Empty;
}
public static Func<T> CompileFunc<[System.Runtime.CompilerServices.Nullable(2)] T>(this Expression<Func<T>> expression)
{
return (Func<T>)expression.CompileDelegate();
}
public static Func<T1, T> CompileFunc<[System.Runtime.CompilerServices.Nullable(2)] T1, [System.Runtime.CompilerServices.Nullable(2)] T>(this Expression<Func<T1, T>> expression)
{
return (Func<T1, T>)expression.CompileDelegate();
}
public static BinaryExpression AssignTo(this Expression left, Expression right)
{
return Expression.Assign(left, right);
}
public static MemberAssignment AssignTo(this MemberInfo memberInfo, Expression expression)
{
return Expression.Bind(memberInfo, expression);
}
public static ConstantExpression AsConstant([System.Runtime.CompilerServices.Nullable(2)] this object obj)
{
return Expression.Constant(obj);
}
public static ConstantExpression AsConstant([System.Runtime.CompilerServices.Nullable(2)] this object obj, Type type)
{
return Expression.Constant(obj, type);
}
public static DefaultExpression AsDefault(this Type type)
{
return Expression.Default(type);
}
public static BlockExpression AsBlock(this IEnumerable<Expression> expressions, params ParameterExpression[] variables)
{
return Expression.Block(variables, expressions);
}
internal static BlockExpression AsBlock(this ExpandableArray<Expression> expressions, params ParameterExpression[] variables)
{
return Expression.Block(variables, expressions);
}
private static BlockExpression AsBlock(this ExpandableArray<Expression> expressions, IEnumerable<ParameterExpression> variables)
{
return Expression.Block(variables, expressions);
}
public static LambdaExpression AsLambda(this Expression expression, params ParameterExpression[] parameters)
{
return Expression.Lambda(expression, parameters);
}
public static LambdaExpression AsLambda(this Expression expression, Type delegateType, IEnumerable<ParameterExpression> parameters)
{
return Expression.Lambda(delegateType, expression, parameters);
}
public static LambdaExpression AsLambda(this Expression expression, Type delegateType, params ParameterExpression[] parameters)
{
return Expression.Lambda(delegateType, expression, parameters);
}
public static LambdaExpression AsLambda(this Expression expression, IEnumerable<ParameterExpression> parameters)
{
return Expression.Lambda(expression, parameters);
}
public static Expression<TDelegate> AsLambda<[System.Runtime.CompilerServices.Nullable(2)] TDelegate>(this Expression expression, params ParameterExpression[] parameters)
{
return Expression.Lambda<TDelegate>(expression, parameters);
}
public static ParameterExpression AsVariable(this Type type, [System.Runtime.CompilerServices.Nullable(2)] string name = null)
{
return Expression.Variable(type, name);
}
public static ParameterExpression AsParameter(this Type type, [System.Runtime.CompilerServices.Nullable(2)] string name = null)
{
return Expression.Parameter(type, name);
}
public static MethodCallExpression CallStaticMethod(this MethodInfo methodInfo, params Expression[] parameters)
{
return Expression.Call(methodInfo, parameters);
}
public static MethodCallExpression CallStaticMethod(this MethodInfo methodInfo, IEnumerable<Expression> parameters)
{
return Expression.Call(methodInfo, parameters);
}
public static MethodCallExpression CallMethod(this Expression target, MethodInfo methodInfo, params Expression[] parameters)
{
return Expression.Call(target, methodInfo, parameters);
}
public static MethodCallExpression CallMethod(this Expression target, MethodInfo methodInfo, IEnumerable<Expression> parameters)
{
return Expression.Call(target, methodInfo, parameters);
}
public static MethodCallExpression CallMethod(this MethodInfo methodInfo, Expression target, params Expression[] parameters)
{
return target.CallMethod(methodInfo, parameters);
}
public static MethodCallExpression CallMethod(this MethodInfo methodInfo, Expression target, IEnumerable<Expression> parameters)
{
return target.CallMethod(methodInfo, parameters);
}
public static Expression ConvertTo(this Expression expression, Type type)
{
return Expression.Convert(expression, type);
}
public static InvocationExpression InvokeLambda(this LambdaExpression expression, params Expression[] parameters)
{
return Expression.Invoke(expression, parameters);
}
public static InvocationExpression InvokeDelegate(this Delegate delegate, params Expression[] parameters)
{
return Expression.Invoke(delegate.AsConstant(), parameters);
}
public static InvocationExpression InvokeDelegate(this Delegate delegate, IEnumerable<Expression> parameters)
{
return Expression.Invoke(delegate.AsConstant(), parameters);
}
public static NewExpression MakeNew(this ConstructorInfo constructor, IEnumerable<Expression> arguments)
{
return Expression.New(constructor, arguments);
}
public static NewExpression MakeNew(this ConstructorInfo constructor, params Expression[] arguments)
{
return Expression.New(constructor, arguments);
}
public static MemberExpression Member(this Expression expression, MemberInfo memberInfo)
{
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
if ((object)propertyInfo == null)
return Expression.Field(expression, (FieldInfo)memberInfo);
return Expression.Property(expression, propertyInfo);
}
public static MemberExpression Prop(this Expression expression, PropertyInfo propertyInfo)
{
return Expression.Property(expression, propertyInfo);
}
public static MemberExpression Access(this PropertyInfo propertyInfo, Expression expression)
{
return Expression.Property(expression, propertyInfo);
}
public static MemberInitExpression InitMembers(this Expression expression, IEnumerable<MemberBinding> bindings)
{
return Expression.MemberInit((NewExpression)expression, bindings);
}
public static MemberInitExpression InitMembers(this Expression expression, params MemberBinding[] bindings)
{
return Expression.MemberInit((NewExpression)expression, bindings);
}
public static NewArrayExpression InitNewArray(this Type type, params Expression[] initializerExpressions)
{
return Expression.NewArrayInit(type, initializerExpressions);
}
public static NewArrayExpression InitNewArray(this Type type, IEnumerable<Expression> initializerExpressions)
{
return Expression.NewArrayInit(type, initializerExpressions);
}
}
}