示例#1
0
 public ExpressionService(ExpressionFeatures features = ExpressionFeatures.None, TraceSource trace = null)
 {
     _features = features;
     _trace    = trace;
     _trace?.TraceInformation($"ExpressionService instantiated with these features: {features}");
     _trace?.Flush();
 }
示例#2
0
        private static void EmitMethodSignatures(ExpressionFeatures features, StringBuilder sb, string expressionLine,
                                                 string[] parameterNames, TraceSource trace)
        {
            Func <string, string> parameterLine = type => EmitExpressionParameters(type, parameterNames);

            if (parameterNames.Length == 0)
            {
                // Nothing:
                sb.AppendLine($"        public static object Evaluate()");
                sb.AppendLine($"        {{");
                sb.AppendLine($"            return {expressionLine};");
                sb.AppendLine($"        }}");
            }
            else
            {
                if (features.HasFlag(ExpressionFeatures.UseDynamicBinding))
                {
                    // Dynamic:
                    sb.AppendLine($"        public static object Evaluate({parameterLine("dynamic")})");
                    sb.AppendLine($"        {{");
                    sb.AppendLine($"            return {expressionLine};");
                    sb.AppendLine($"        }}");
                }
                else
                {
                    // Permutations:
                    EmitTypePermutation(sb, expressionLine, parameterNames, TypePermutations1);
                }
            }
        }
示例#3
0
            public override object Invoke(ExpressionFeatures features, Type[] types, object[] values)
            {
                MethodInfo eval   = GetEvaluationMethod(features, types);
                object     result = eval.Invoke(null, values);

                return(result);
            }
示例#4
0
        public void Compare_constants_versus_native(ExpressionFeatures features, int trials)
        {
            ExpressionService service = new ExpressionService(features);

            // Constants:
            CompareTests("Constants",
                         features.ToString(), () => service.Evaluate("100", null, null, null),
                         "Native", () => ConstantNative(),
                         trials, service, 100);
        }
示例#5
0
        public static IExecutionContext Compile(ExpressionFeatures features, string expression, string[] parameterNames, AppDomain domain = null)
        {
            string expressionLine = $"{{{{ '{expression}' | inline_functions | clean }}}}";

            StringBuilder sb = new StringBuilder();

            sb.AppendLine($"namespace Expressions");
            sb.AppendLine($"{{");
            sb.AppendLine($"    public static class Expression");
            sb.AppendLine($"    {{");

            EmitMethodSignatures(features, sb, expressionLine, parameterNames);

            sb.AppendLine($"    }}");
            sb.AppendLine($"}}");
            string source = sb.ToString();

            Template template = Template.Parse(source);
            string   code     = template.Render(Hash.FromAnonymousObject(new
            {
                expression
            }));

            // Note: GenerateInMemory still creates an assembly on disk!
            CompilerParameters p = new CompilerParameters
            {
                WarningLevel       = 4,
                GenerateExecutable = false,
                GenerateInMemory   = domain == null,
                CompilerOptions    = "/optimize"
            };

            if (features.HasFlag(ExpressionFeatures.UseDynamic))
            {
                p.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
                p.ReferencedAssemblies.Add("System.Core.dll");
            }

            CodeDomProvider compiler = new CSharpCodeProvider();
            CompilerResults r        = compiler.CompileAssemblyFromSource(p, code);

            // load into AppDomain.Current
            if (domain == null || domain == AppDomain.CurrentDomain)
            {
                return(new LocalExecutor(r.CompiledAssembly));
            }

            // load assembly into another app domain (without leaking into this one)
            RemoteExecutor remote = (RemoteExecutor)domain.CreateInstanceAndUnwrap(typeof(RemoteExecutor).Assembly.FullName, typeof(RemoteExecutor).FullName);

            remote.LoadFrom(r.PathToAssembly);
            return(remote);
        }
示例#6
0
            private MethodInfo GetEvaluationMethod(ExpressionFeatures features, Type[] types)
            {
                // L2 Cache: MethodInfo
                if (features.HasFlag(ExpressionFeatures.L2Cache))
                {
                    string     key = $"{Identifier}_{types.Select(t => t.Name)}";
                    MethodInfo eval;
                    if (MethodCache.Value.TryGetMethod(key, out eval))
                    {
                        return(eval);
                    }
                    return(MethodCache.Value.Add(key, GetMethod(types)));
                }

                return(GetMethod(types));
            }
示例#7
0
 public QxOptions WithAllowedFeatures(ExpressionFeatures allowedFeatures) =>
 new QxOptions(AllowedFeatures | allowedFeatures, AllowedMembers);
示例#8
0
 public QxOptions(ExpressionFeatures allowedFeatures, IEnumerable <MemberInfo> allowedMembers)
 {
     AllowedFeatures = allowedFeatures;
     AllowedMembers  = allowedMembers;
 }
示例#9
0
 public abstract object Invoke(ExpressionFeatures features, Type[] types, object[] values);
示例#10
0
        private static void EmitMethodSignatures(ExpressionFeatures features, StringBuilder sb, string expressionLine, string[] parameterNames)
        {
            Func <string, string> parameterLine = type => EmitExpressionParameters(type, parameterNames);

            if (parameterNames.Length == 0)
            {
                // Nothing:
                sb.AppendLine($"        public static object Evaluate()");
                sb.AppendLine($"        {{");
                sb.AppendLine($"            return {expressionLine};");
                sb.AppendLine($"        }}");

                return;
            }

            if (features.HasFlag(ExpressionFeatures.UseDynamic))
            {
                // Dynamic:
                sb.AppendLine($"        public static dynamic Evaluate({parameterLine("dynamic")})");
                sb.AppendLine($"        {{");
                sb.AppendLine($"            return {expressionLine};");
                sb.AppendLine($"        }}");

                return;
            }

            // Byte:
            sb.AppendLine($"        public static object Evaluate({parameterLine("byte")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");

            // Int16:
            sb.AppendLine($"        public static object Evaluate({parameterLine("short")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");

            // Int32:
            sb.AppendLine($"        public static object Evaluate({parameterLine("int")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");

            // Int64:
            sb.AppendLine($"        public static object Evaluate({parameterLine("long")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");

            // Single:
            sb.AppendLine($"        public static object Evaluate({parameterLine("float")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");

            // Double:
            sb.AppendLine($"        public static object Evaluate({parameterLine("double")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");

            // Decimal:
            sb.AppendLine($"        public static object Evaluate({parameterLine("decimal")})");
            sb.AppendLine($"        {{");
            sb.AppendLine($"            return {expressionLine};");
            sb.AppendLine($"        }}");
        }
示例#11
0
        public static IExecutionContext Compile(string expression, string[] parameterNames, TraceSource trace,
                                                ExpressionFeatures features, string @namespace = "MyNamespace", AppDomain domain = null)
        {
            const string ls = "{{";
            const string le = "}}";

            string expressionLine = $"{ls}expression{le}";

            StringBuilder sb = new StringBuilder();

            sb.AppendLine($"using System.ComponentModel;");
            sb.AppendLine();
            sb.AppendLine($"namespace {@namespace}");
            sb.AppendLine($"{{");
            sb.AppendLine($"    [Description(\"{expression}\")]");
            sb.AppendLine($"    public static class Expression");
            sb.AppendLine($"    {{");

            EmitMethodSignatures(features, sb, expressionLine, parameterNames, trace);

            sb.AppendLine($"    }}");
            sb.AppendLine($"}}");
            string source = sb.ToString();

            Template template = Template.Parse(source);
            string   code     = template.Render(Hash.FromAnonymousObject(new
            {
                expression
            }));

            trace?.TraceInformation($"Compiling expression: {expression}");
            trace?.TraceInformation(code);
            trace?.Flush();

            // Note: GenerateInMemory still creates an assembly on disk!
            CompilerParameters p = new CompilerParameters
            {
                WarningLevel       = 4,
                GenerateExecutable = false,
                GenerateInMemory   = domain == null,
                CompilerOptions    = "/optimize"
            };

            p.ReferencedAssemblies.Add(typeof(DescriptionAttribute).Assembly.Location);

            if (features.HasFlag(ExpressionFeatures.UseDynamicBinding))
            {
                p.ReferencedAssemblies.Add(typeof(DynamicAttribute).Assembly.Location);
                p.ReferencedAssemblies.Add(typeof(Microsoft.CSharp.RuntimeBinder.Binder).Assembly.Location);
            }

            CodeDomProvider compiler = new CSharpCodeProvider();
            CompilerResults r        = compiler.CompileAssemblyFromSource(p, code);

            if (r.Errors.Count > 0)
            {
                trace?.TraceEvent(TraceEventType.Error, 500, "Compiler errors encountered");
                foreach (CompilerError error in r.Errors.OfType <CompilerError>().Where(e => e.IsWarning))
                {
                    trace?.TraceEvent(TraceEventType.Warning, 500, error.ToString());
                }
                foreach (CompilerError error in r.Errors.OfType <CompilerError>().Where(e => !e.IsWarning))
                {
                    trace?.TraceEvent(TraceEventType.Error, 500, error.ToString());
                }
            }

            // load into AppDomain.Current
            if (domain == null || domain == AppDomain.CurrentDomain)
            {
                return(new LocalExecutor(r.CompiledAssembly));
            }

            // load assembly into isolated app domain (without leaking into this one)
            RemoteExecutor remote =
                (RemoteExecutor)
                domain.CreateInstanceAndUnwrap(typeof(RemoteExecutor).Assembly.FullName,
                                               typeof(RemoteExecutor).FullName);

            remote.LoadFrom(r.PathToAssembly);
            return(remote);
        }
示例#12
0
 public ExpressionService(ExpressionFeatures features = ExpressionFeatures.Default)
 {
     _features = features;
 }
示例#13
0
 public AllowedFeaturesScanner(ExpressionFeatures features)
 {
     _features = features;
 }
示例#14
0
 public static Verifier Create(ExpressionFeatures features) =>
 Verification.CreatePatternedVerifier(new AllowedFeaturesScanner(features).Scan);