コード例 #1
0
        /// <summary>
        /// Compile C# source code
        /// </summary>
        /// <param name="sourcePath">path to source</param>
        /// <param name="moreReferences">additional library references</param>
        /// <returns>compiled assembly</returns>
        public static Assembly CompileSource(string sourcePath, MetadataReference[] moreReferences = null)
        {
            string     sourceText = File.ReadAllText(sourcePath);
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(
                sourceText,
                path: sourcePath,
                encoding: System.Text.Encoding.UTF8);

            string assemblyName = Path.GetRandomFileName();

            var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);

            MetadataReference[] references = new MetadataReference[]
            {
                //--- these can't be created any other way
                //    https://stackoverflow.com/questions/23907305/roslyn-has-no-reference-to-system-runtime
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "mscorlib.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Core.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Data.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Collections.dll")),
                MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")),

                //--- these are referenced by a type we need
                //MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(TuringTrader.Simulator.Algorithm).GetTypeInfo().Assembly.Location),
                //MetadataReference.CreateFromFile(typeof(TuringTrader.Indicators.IndicatorsBasic).GetTypeInfo().Assembly.Location),

                //--- this is what we used with CodeDOM

                /*
                 * cp.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
                 * cp.ReferencedAssemblies.Add("System.dll");
                 * cp.ReferencedAssemblies.Add("System.Runtime.dll");
                 * cp.ReferencedAssemblies.Add("System.Collections.dll");
                 * cp.ReferencedAssemblies.Add("System.Core.dll");
                 * cp.ReferencedAssemblies.Add("System.Data.dll");
                 * cp.ReferencedAssemblies.Add("OxyPlot.dll");
                 * cp.ReferencedAssemblies.Add("OxyPlot.Wpf.dll");
                 */
            };

            if (moreReferences != null)
            {
                foreach (var r in moreReferences)
                {
                    references = references.Append(r).ToArray();
                }
            }

            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees: new[] { syntaxTree },
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (var dll = new MemoryStream())
                using (var pdb = new MemoryStream())
                {
                    EmitResult result = compilation.Emit(dll, pdb);

                    if (!result.Success)
                    {
                        IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                                                                                     diagnostic.IsWarningAsError ||
                                                                                     diagnostic.Severity == DiagnosticSeverity.Error);

                        foreach (Diagnostic diagnostic in failures)
                        {
                            // find error location and line number
                            int    errorChar   = diagnostic.Location.SourceSpan.Start;
                            string errorSource = sourceText.Substring(0, errorChar);
                            int    lineNumber  = errorSource.Split('\n').Length;

                            Output.WriteLine("Line {0}: {1} - {2}",
                                             lineNumber,
                                             diagnostic.Id,
                                             diagnostic.GetMessage());
                        }
                    }
                    else
                    {
                        dll.Seek(0, SeekOrigin.Begin);
                        pdb.Seek(0, SeekOrigin.Begin);

                        Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(dll, pdb);
                        return(assembly);
                    }
                }


            return(null);
        }