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); }
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); }