如何在运行时在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,并使用反射来获取创建类图的类和方法。