Esempio n. 1
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);
        }
Esempio n. 2
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);
        }