如何在运行时在C#Dot Net中编译代码?

如何在运行时在C#Dot Net中编译代码?,c#,compilation,C#,Compilation,因此,我想编译一个包含.cs文件的完整文件夹,然后创建一个DLL文件,然后在运行时的项目中使用该DLL 我搜索了互联网,发现CSharpCodeProvider可以在这方面帮助我 但让我困惑的是,这个网站上的大多数示例都展示了如何读取单个文件,而不是整个文件夹 因此,我假设包含.cs文件的文件夹将链接在一起。 示例文件: 文件:TestMain.cs class TestMain { public static void Main(string[] args)

因此,我想编译一个包含
.cs
文件的完整文件夹,然后创建一个DLL文件,然后在运行时的项目中使用该DLL

我搜索了互联网,发现
CSharpCodeProvider
可以在这方面帮助我

但让我困惑的是,这个网站上的大多数示例都展示了如何读取单个文件,而不是整个文件夹

因此,我假设包含
.cs
文件的文件夹将链接在一起。 示例文件:

文件:
TestMain.cs

class TestMain
    {
        public static void Main(string[] args)
        {
            Test t = new Test();
            t.Hello();
        }
    }
public class Test
    {
        public void Hello()
        {
            Console.Write(@"Hello");
        }
    }
文件:
Test.cs

class TestMain
    {
        public static void Main(string[] args)
        {
            Test t = new Test();
            t.Hello();
        }
    }
public class Test
    {
        public void Hello()
        {
            Console.Write(@"Hello");
        }
    }

任何指导都会很受欢迎。

基本上,你可以使用
CodeDom.Compiler
来编译dll,我很久以前写过类似这样的东西,然后使用
反射
来动态引用它

string sourceCode = @"
    public class Test
    {
       public void Hello()
       {
          Console.Write(@'Hello');
       }
    }";

    var compParms = new CompilerParameters{
        GenerateExecutable = false, 
        GenerateInMemory = true
    };

    var csProvider = new CSharpCodeProvider();
    CompilerResults compilerResults = 
            csProvider.CompileAssemblyFromSource(compParms, sourceCode);
    object typeInstance = 
            compilerResults.CompiledAssembly.CreateInstance("Test");
    MethodInfo mi = typeInstance.GetType().GetMethod("Hello");
    mi.Invoke(typeInstance, null); 
    Console.ReadLine();
//dot net compiler
using System; 
using System.CodeDom.Compiler; 
using System.IO; 

namespace IndiLogix.dotCompiler 
{ 
    class dotCompiler 
    { 
        FileInfo sourceFile;// = new FileInfo(sourceName); 
        CodeDomProvider provider = null; 
        bool compileOk = false; 


        // Compile Executable 
        public bool CompileExecutable(String sourceName) 
        { 
            sourceFile = new FileInfo(sourceName); 
            I_GetProvider(sourceFile); 
            if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".CS") 
            { 
                provider = CodeDomProvider.CreateProvider("CSharp"); 
                //return "CSharp"; 
            } 

            if (provider != null) 
            { 

                // Format the executable file name. 
                // Build the output assembly path using the current directory 
                // and _cs.exe or _vb.exe. 

                String exeName = String.Format(@"{0}\{1}.exe", 
                System.Environment.CurrentDirectory, 
                sourceFile.Name.Replace(".", "_")); 
                string dllName = String.Format(@"{0}\{1}.dll", System.Environment.CurrentDirectory, sourceFile.Name.Replace(".", "_")); 

                CompilerParameters cp = new CompilerParameters(); 

                // Generate an executable instead of a class library. 
                cp.GenerateExecutable = true; 

                // Specify the assembly file name to generate. 
                cp.OutputAssembly = exeName; 

                // Save the assembly as a physical file. 
                cp.GenerateInMemory = false; 

                // Set whether to treat all warnings as errors. 
                cp.TreatWarningsAsErrors = false; 

                // Invoke compilation of the source file. 
                CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceName); 
                string temp; 
                if (cr.Errors.Count > 0) 
                { 
                    // Display compilation errors. 
                    temp = sourceName + "\n" + cr.PathToAssembly; 

                    foreach (CompilerError ce in cr.Errors) 
                    { 
                        temp += "\nError:" + ce.ToString(); 
                    } 
                    System.Windows.Forms.MessageBox.Show(temp, "dotCompiler Error:", System.Windows.Forms.MessageBoxButtons.OK); 
                } 
                else 
                { 
                    // Display a successful compilation message. 
                    //Console.WriteLine("Source {0} built into {1} successfully.",sourceName, cr.PathToAssembly); 
                    System.Windows.Forms.MessageBox.Show("Solution build sucessfully..\n\n" + sourceName + "\n" + cr.PathToAssembly,"dotCompiler:)",System.Windows.Forms.MessageBoxButtons.OK); 
                } 

                // Return the results of the compilation. 
                if (cr.Errors.Count > 0) 
                { 
                    compileOk = false; 
                } 
                else 
                { 
                    compileOk = true; 
                } 
            } 
            return compileOk; 
        } 

        private void I_GetProvider(FileInfo sourceFile) 
        { 
            // Select the code provider based on the input file extension. 
            if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".CS") 
            { 
                provider = CodeDomProvider.CreateProvider("CSharp"); 
            } 
            else if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".VB") 
            { 
                provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("VisualBasic"); 
            } 
            else 
            { 
                //Console.WriteLine("Source file must have a .cs or .vb extension"); 
                //_Notify("Error:", "Source file must have a .cs or .vb extension", ToolTipIcon.Error); 
                System.Windows.Forms.MessageBox.Show( 
                "Source file must have *.cs or *.vb extension", "dotCompiler Error", 
                System.Windows.Forms.MessageBoxButtons.OK); 
            } 
        } 

        private string I_GetProvider_RetStr(FileInfo sourceFile) 
        { 

            // Select the code provider based on the input file extension. 
            if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".CS") 
            { 
                provider = CodeDomProvider.CreateProvider("CSharp"); 
                return "CSharp"; 
            } 
            else if (sourceFile.Extension.ToUpper(System.Globalization.CultureInfo.InvariantCulture) == ".VB") 
            { 
                provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("VisualBasic"); 
                return "VisualBasic"; 
            } 
            else 
            { 
                //Console.WriteLine("Source file must have a .cs or .vb extension"); 
                //_Notify("Error:", "Source file must have a .cs or .vb extension", ToolTipIcon.Error); 
                return "Source file must have *.cs or *.vb extension"; 
            } 
        } 

        public bool CompileDll(String sourceName) 
        { 

            sourceFile = new FileInfo(sourceName); 
            I_GetProvider(sourceFile); 

            if (provider != null) 
            { 

            // Format the executable file name. 
            // Build the output assembly path using the current directory 
            // and _cs.exe or _vb.exe. 

            String exeName = String.Format(@"{0}\{1}.exe", 
            System.Environment.CurrentDirectory, 
            sourceFile.Name.Replace(".", "_")); 
            string dllName = String.Format(@"{0}\{1}.dll", System.Environment.CurrentDirectory, sourceFile.Name.Replace(".", "_")); 

            CompilerParameters cp = new CompilerParameters(); 

            // Generate an executable instead of a class library. 
            cp.GenerateExecutable = false; 

            // Specify the assembly file name to generate. 
            cp.OutputAssembly = dllName; 

            // Save the assembly as a physical file. 
            cp.GenerateInMemory = false; 

            // Set whether to treat all warnings as errors. 
            cp.TreatWarningsAsErrors = false; 

            // Invoke compilation of the source file. 
            CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceName); 
            string temp; 
            if (cr.Errors.Count > 0) 
            { 
            // Display compilation errors. 
            temp = "compiling " + sourceName + " to " + cr.PathToAssembly; 

            foreach (CompilerError ce in cr.Errors) 
            { 
            temp += "\nError:" + ce.ToString(); 
            } 

                System.Windows.Forms.MessageBox.Show(temp, "dotCompiler Error:", System.Windows.Forms.MessageBoxButtons.OK); 
            } 
            else 
            { 
                // Display a successful compilation message. 
                //Console.WriteLine("Source {0} built into {1} successfully.",sourceName, cr.PathToAssembly); 
                System.Windows.Forms.MessageBox.Show("Solution build sucessfully..\n\n" + sourceName + "\n" + cr.PathToAssembly, "dotCompiler:)", System.Windows.Forms.MessageBoxButtons.OK); 
            } 

                // Return the results of the compilation. 
                if (cr.Errors.Count > 0) 
                { 
                    compileOk = false; 
                } 
                else 
                { 
                    compileOk = true; 
                } 
            } 
        return compileOk; 
        } 

    } 
} 

在搜索和指导之后,这里是我的工作代码:

public static Assembly CompileAssembly(string[] sourceFiles, string outputAssemblyPath)
        {
            var codeProvider = new CSharpCodeProvider();

            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = false,
                OutputAssembly = outputAssemblyPath
            };

            // Add CSharpSimpleScripting.exe as a reference to Scripts.dll to expose interfaces
            //compilerParameters.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);

            var result = codeProvider.CompileAssemblyFromFile(compilerParameters, sourceFiles); // Compile
            if (result.Errors.Count > 0)
            {
                MessageBox.Show(@"Error Occured");
            }
            else
            {
                return result.CompiledAssembly;

            }
            return null;
        }

我理解你的代码。但如果我必须编译一个完整的文件夹呢?@idenny,下面的例子“编译文件夹”本身并不意味着什么。您的意思是单独编译每个cs文件还是创建一个lerger程序集?当然,我们可以将文件夹中具有相同名称空间的.cs文件编译成一个DLL文件,以后我可以在运行时在项目中使用它。为什么要这样做?有什么原因吗?我和拉胡尔有同样的问题。这对我来说似乎是一个XY问题,你到底想实现什么?我正在创建一个项目,它从文件夹中读取.cs文件,推断出没有类和方法变量等,并使用这些信息创建类图,所以你只有一堆.cs文件,没有csproj文件?嗯,是的,我只有.cs文件。如果我没有错的话,你只编译了一个文件。是的,它只针对一个文件,但有一个解决方法。如果有示例代码,将不胜感激。我还找到了这个资源,请检查和verify@idenny我不知道这里的要求是什么,但您也可以检查提供类似脚本的CS脚本functionality@idenny使用CodeDomProvider.CompileAssemblyFromFile方法,可以指定多个文件,但是我建议在源目录中使用csc作为csc/out:mydll.dll*.cs,并使用反射来获取创建类图的类和方法。