예제 #1
0
        private static Type DoActualCompilation(string source, string name, string queryText, OrderedPartCollection <AbstractDynamicCompilationExtension> extensions,
                                                string basePath, string indexFilePath)
        {
            var provider = new CSharpCodeProvider(new Dictionary <string, string> {
                { "CompilerVersion", "v4.0" }
            });
            var assemblies = new HashSet <string>
            {
                typeof(SystemTime).Assembly.Location,
                typeof(AbstractViewGenerator).Assembly.Location,
                typeof(NameValueCollection).Assembly.Location,
                typeof(Enumerable).Assembly.Location,
                typeof(Binder).Assembly.Location,
                typeof(Field).Assembly.Location,
            };

            foreach (var extension in extensions)
            {
                foreach (var assembly in extension.Value.GetAssembliesToReference())
                {
                    assemblies.Add(assembly);
                }
            }
            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable      = false,
                GenerateInMemory        = false,
                IncludeDebugInformation = Debugger.IsAttached,
                OutputAssembly          = indexFilePath
            };

            if (basePath != null)
            {
                compilerParameters.TempFiles = new TempFileCollection(basePath, false);
            }

            foreach (var assembly in assemblies)
            {
                compilerParameters.ReferencedAssemblies.Add(assembly);
            }

            CompilerResults compileAssemblyFromFile;

            if (indexFilePath != null)
            {
                var sourceFileName = indexFilePath + ".cs";
                File.WriteAllText(sourceFileName, source);
                compileAssemblyFromFile = provider.CompileAssemblyFromFile(compilerParameters, sourceFileName);
            }
            else
            {
                compileAssemblyFromFile = provider.CompileAssemblyFromSource(compilerParameters, source);
            }
            var results = compileAssemblyFromFile;

            if (results.Errors.HasErrors)
            {
                var sb = new StringBuilder()
                         .AppendLine("Compilation Errors:")
                         .AppendLine();

                foreach (CompilerError error in results.Errors)
                {
                    sb.AppendFormat("Line {0}, Position {1}: Error {2} - {3}\n", error.Line, error.Column, error.ErrorNumber, error.ErrorText);
                }

                sb.AppendLine();

                sb.AppendLine("Source code:")
                .AppendLine(queryText)
                .AppendLine();

                throw new InvalidOperationException(sb.ToString());
            }

            var asm = Assembly.Load(File.ReadAllBytes(indexFilePath));             // avoid locking the file

            CodeVerifier.AssertNoSecurityCriticalCalls(asm);

            Type result = asm.GetType(name);

            if (result == null)
            {
                throw new InvalidOperationException(
                          "Could not get compiled index type. This probably means that there is something wrong with the assembly load context.");
            }
            return(result);
        }
예제 #2
0
        public static Type Compile(string source, string name, string queryText, OrderedPartCollection <AbstractDynamicCompilationExtension> extensions, string basePath)
        {
            source = source.Replace("AbstractIndexCreationTask.SpatialGenerate", "SpatialGenerate");             // HACK, should probably be on the client side

            CacheEntry entry;

            if (cacheEntries.TryGetValue(source, out entry))
            {
                Interlocked.Increment(ref entry.Usages);
                return(entry.Type);
            }

            var provider = new CSharpCodeProvider(new Dictionary <string, string> {
                { "CompilerVersion", "v4.0" }
            });
            var assemblies = new HashSet <string>
            {
                typeof(SystemTime).Assembly.Location,
                typeof(AbstractViewGenerator).Assembly.Location,
                typeof(NameValueCollection).Assembly.Location,
                typeof(Enumerable).Assembly.Location,
                typeof(Binder).Assembly.Location,
                typeof(Field).Assembly.Location
            };

            foreach (var extension in extensions)
            {
                foreach (var assembly in extension.Value.GetAssembliesToReference())
                {
                    assemblies.Add(assembly);
                }
            }
            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable      = false,
                GenerateInMemory        = true,
                IncludeDebugInformation = false
            };

            if (basePath != null)
            {
                compilerParameters.TempFiles = new TempFileCollection(basePath, false);
            }

            foreach (var assembly in assemblies)
            {
                compilerParameters.ReferencedAssemblies.Add(assembly);
            }
            var compileAssemblyFromFile = provider.CompileAssemblyFromSource(compilerParameters, source);
            var results = compileAssemblyFromFile;

            if (results.Errors.HasErrors)
            {
                var sb = new StringBuilder()
                         .AppendLine("Source code:")
                         .AppendLine(queryText)
                         .AppendLine();
                foreach (CompilerError error in results.Errors)
                {
                    sb.AppendLine(error.ToString());
                }
                throw new InvalidOperationException(sb.ToString());
            }

            CodeVerifier.AssertNoSecurityCriticalCalls(results.CompiledAssembly);

            Type result = results.CompiledAssembly.GetType(name);

            cacheEntries.TryAdd(source, new CacheEntry
            {
                Source = source,
                Type   = result,
                Usages = 1
            });

            if (cacheEntries.Count > 256)
            {
                var kvp = cacheEntries.OrderBy(x => x.Value.Usages).FirstOrDefault();
                if (kvp.Key != null)
                {
                    CacheEntry _;
                    cacheEntries.TryRemove(kvp.Key, out _);
                }
            }

            return(result);
        }