コード例 #1
0
        /// <summary>Resolve parameters used for the code or expression.</summary>
        /// <param name="scope">The expression scope for the code or expression to compile.</param>
        /// <param name="parameterKind">The parameter kind for the code or expression to compile.</param>
        /// <param name="parameterTypes">The dictionary of parameter (name / type) used in the code or expression to compile.</param>
        /// <returns>A ParameterExpression list used in code or expression to compile.</returns>
        private static List<ParameterExpression> ResolveParameter(ExpressionScope scope, EvalCompilerParameterKind parameterKind, IDictionary<string, Type> parameterTypes)
        {
            if (parameterTypes == null) return null;

            List<ParameterExpression> parameterExpressions;

            switch (parameterKind)
            {
                case EvalCompilerParameterKind.Dictionary:
                    parameterExpressions = ResolveParameterDictionary(scope, parameterTypes);
                    break;
                case EvalCompilerParameterKind.Enumerable:
                    parameterExpressions = ResolveParameterEnumerable(scope, parameterTypes);
                    break;
                case EvalCompilerParameterKind.SingleDictionary:
                    parameterExpressions = ResolveParameterSingleDictionary(scope, parameterTypes);
                    break;
                case EvalCompilerParameterKind.Typed:
                    parameterExpressions = ResolveParameterTyped(scope, parameterTypes);
                    break;
                case EvalCompilerParameterKind.Untyped:
                    parameterExpressions = ResolveParameterUntyped(scope, parameterTypes);
                    break;
                default:
                    parameterExpressions = new List<ParameterExpression>();
                    break;
            }

            return parameterExpressions;
        }
コード例 #2
0
        /// <summary>Compile the code or expression and return a TDelegate of type Func or Action to execute.</summary>
        /// <typeparam name="TDelegate">Type of the delegate (Func or Action) to use to compile the code or expression.</typeparam>
        /// <param name="context">The eval context used to compile the code or expression.</param>
        /// <param name="code">The code or expression to compile.</param>
        /// <param name="parameterTypes">The dictionary of parameter (name / type) used in the code or expression to compile.</param>
        /// <param name="resultType">Type of the compiled code or expression result.</param>
        /// <param name="parameterKind">The parameter kind for the code or expression to compile.</param>
        /// <returns>A TDelegate of type Func or Action that represents the compiled code or expression.</returns>
        internal static TDelegate Compile <TDelegate>(EvalContext context, string code, IDictionary <string, Type> parameterTypes, Type resultType, EvalCompilerParameterKind parameterKind)
        {
            var cacheKey = context.UseCache ? ResolveCacheKey(context, typeof(TDelegate), code, parameterTypes) : "";

            if (context.UseCache)
            {
                var item = EvalManager.Cache.Get(cacheKey);

                if (item != null)
                {
                    return((TDelegate)item);
                }
            }

            // Options
            var scope = new ExpressionScope
            {
                AliasExtensionMethods = context.AliasExtensionMethods,
                //AliasGlobalConstants = context.AliasGlobalConstants,
                //AliasGlobalVariables = context.AliasGlobalVariables,
                AliasNames          = context.AliasNames,
                AliasStaticMembers  = context.AliasStaticMembers,
                AliasTypes          = context.AliasTypes,
                BindingFlags        = context.BindingFlags,
                UseCaretForExponent = context.UseCaretForExponent
            };

            // Resolve Parameter
            var parameterExpressions = ResolveParameter(scope, parameterKind, parameterTypes);

            // ADD global constants
            if (context.AliasGlobalConstants.Count > 0)
            {
                scope.Constants = new Dictionary <string, ConstantExpression>(context.AliasGlobalConstants);
            }

            // ADD global variables
            if (context.AliasGlobalVariables.Count > 0)
            {
                foreach (var keyValue in context.AliasGlobalVariables)
                {
                    scope.CreateLazyVariable(keyValue.Key, new Lazy <Expression>(() =>
                    {
                        var innerParameter  = scope.CreateVariable(keyValue.Value.GetType(), keyValue.Key);
                        var innerExpression = Expression.Assign(innerParameter, Expression.Constant(keyValue.Value));
                        scope.Expressions.Add(innerExpression);
                        return(innerParameter);
                    }));
                }
            }

            // CodeAnalysis
            var syntaxRoot = SyntaxParser.ParseText(code);

            // CodeCompiler
            var expression = ExpressionParser.ParseSyntax(scope, syntaxRoot, resultType);

            // Compile the expression
            var compiled = Expression.Lambda <TDelegate>(expression, parameterExpressions).Compile();

            if (context.UseCache)
            {
                EvalManager.Cache.AddOrGetExisting(new CacheItem(cacheKey, compiled), new CacheItemPolicy());
            }

            return(compiled);
        }
コード例 #3
0
 /// <summary>Compile the code or expression and return a TDelegate of type Func or Action to execute.</summary>
 /// <typeparam name="TDelegate">Type of the delegate (Func or Action) to use to compile the code or expression.</typeparam>
 /// <param name="context">The eval context used to compile the code or expression.</param>
 /// <param name="code">The code or expression to compile.</param>
 /// <param name="parameterTypes">The dictionary of parameter (name / type) used in the code or expression to compile.</param>
 /// <param name="resultType">Type of the compiled code or expression result.</param>
 /// <param name="parameterKind">The parameter kind for the code or expression to compile.</param>
 /// <returns>A TDelegate of type Func or Action that represents the compiled code or expression.</returns>
 internal static Task <TDelegate> CompileAsync <TDelegate>(EvalContext context, string code, IDictionary <string, Type> parameterTypes, Type resultType, EvalCompilerParameterKind parameterKind)
 {
     return(Task.Run(() => Compile <TDelegate>(context, code, parameterTypes, resultType, parameterKind)));
 }
コード例 #4
0
        /// <summary>Resolve parameters used for the code or expression.</summary>
        /// <param name="scope">The expression scope for the code or expression to compile.</param>
        /// <param name="parameterKind">The parameter kind for the code or expression to compile.</param>
        /// <param name="parameterTypes">The dictionary of parameter (name / type) used in the code or expression to compile.</param>
        /// <returns>A ParameterExpression list used in code or expression to compile.</returns>
        private static List <ParameterExpression> ResolveParameter(ExpressionScope scope, EvalCompilerParameterKind parameterKind, IDictionary <string, Type> parameterTypes)
        {
            if (parameterTypes == null)
            {
                return(null);
            }

            List <ParameterExpression> parameterExpressions;

            switch (parameterKind)
            {
            case EvalCompilerParameterKind.Dictionary:
                parameterExpressions = ResolveParameterDictionary(scope, parameterTypes);
                break;

            case EvalCompilerParameterKind.Enumerable:
                parameterExpressions = ResolveParameterEnumerable(scope, parameterTypes);
                break;

            case EvalCompilerParameterKind.SingleDictionary:
                parameterExpressions = ResolveParameterSingleDictionary(scope, parameterTypes);
                break;

            case EvalCompilerParameterKind.Typed:
                parameterExpressions = ResolveParameterTyped(scope, parameterTypes);
                break;

            case EvalCompilerParameterKind.Untyped:
                parameterExpressions = ResolveParameterUntyped(scope, parameterTypes);
                break;

            default:
                parameterExpressions = new List <ParameterExpression>();
                break;
            }

            return(parameterExpressions);
        }
コード例 #5
0
        /// <summary>Compile the code or expression and return a TDelegate of type Func or Action to execute.</summary>
        /// <typeparam name="TDelegate">Type of the delegate (Func or Action) to use to compile the code or expression.</typeparam>
        /// <param name="context">The eval context used to compile the code or expression.</param>
        /// <param name="code">The code or expression to compile.</param>
        /// <param name="parameterTypes">The dictionary of parameter (name / type) used in the code or expression to compile.</param>
        /// <param name="resultType">Type of the compiled code or expression result.</param>
        /// <param name="parameterKind">The parameter kind for the code or expression to compile.</param>
        /// <returns>A TDelegate of type Func or Action that represents the compiled code or expression.</returns>
        internal static TDelegate Compile <TDelegate>(EvalContext context, string code, IDictionary <string, Type> parameterTypes, Type resultType, EvalCompilerParameterKind parameterKind)
        {
            var cacheKey = ResolveCacheKey(context, typeof(Func <IDictionary, object>), code, parameterTypes);

            EvalDelegate cachedDelegate;

            if (EvalManager.CacheDelegate.TryGetValue(cacheKey, out cachedDelegate))
            {
                return((TDelegate)cachedDelegate.InnerDelegate);
            }

            // Options
            var scope = new ExpressionScope
            {
                AliasExtensionMethods = context.AliasExtensionMethods,
                AliasNames            = context.AliasNames,
                AliasStaticMembers    = context.AliasStaticMembers,
                AliasTypes            = context.AliasTypes,
                BindingFlags          = context.BindingFlags,
                UseCaretForExponent   = context.UseCaretForExponent
            };

            // Resolve Parameter
            var parameterExpressions = ResolveParameter(scope, parameterKind, parameterTypes);

            // ADD global constants
            if (context.AliasGlobalConstants.Count > 0)
            {
                scope.Constants = new Dictionary <string, ConstantExpression>(context.AliasGlobalConstants);
            }

            // ADD global variables
            if (context.AliasGlobalVariables.Count > 0)
            {
                foreach (var keyValue in context.AliasGlobalVariables)
                {
                    scope.CreateLazyVariable(keyValue.Key, new LazySingleThread <Expression>(() =>
                    {
                        var innerParameter = scope.CreateVariable(keyValue.Value.GetType(), keyValue.Key);
                        var innerExpression = Expression.Assign(innerParameter, Expression.Constant(keyValue.Value));
                        scope.Expressions.Add(innerExpression);
                        return(innerParameter);
                    }));
                }
            }

            // CodeAnalysis
            var syntaxRoot = SyntaxParser.ParseText(code);

            // CodeCompiler
            var expression = ExpressionParser.ParseSyntax(scope, syntaxRoot, resultType);

            // Compile the expression
            var compiled = Expression.Lambda <TDelegate>(expression, parameterExpressions).Compile();

            var evalDelegate = new EvalDelegate(cacheKey, null);

            evalDelegate.InnerDelegate = compiled;

            EvalManager.CacheDelegate.TryAdd(cacheKey, evalDelegate);

            return(compiled);
        }