C# 动态加载程序集
C# Loading assemblies dynamically
我在运行时将文本编译成动态对象时遇到问题。
我写了一段简单的代码编译文案:
public class CompileFactory
{
public dynamic Compile(String classCode, String mainClass, Object[] requiredAssemblies)
{
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string>
{
{ "CompilerVersion", "v4.0" }
});
CompilerParameters parameters = new CompilerParameters
{
GenerateExecutable = true, // Create a dll
GenerateInMemory = true, // Create it in memory
WarningLevel = 3, // Default warning level
CompilerOptions = "/optimize", // Optimize code
TreatWarningsAsErrors = false // Better be false to avoid break in warnings
};
// Add all extra assemblies required
foreach (var extraAsm in requiredAssemblies)
{
parameters.ReferencedAssemblies.Add(extraAsm as string);
}
CompilerResults results = provider.CompileAssemblyFromSource(parameters, classCode);
if (results.Errors.Count != 0)
{
return "FAILED";
}
return results.CompiledAssembly.CreateInstance(mainClass); ;
}
}
这就是我使用 Compile
方法的方式。
List<string> assemblies = new List<string>{"System.Net.Mail.dll", "System.Net.dll"};
dynamic obj = compile.Compile(fileText, pluginName, assemblies.ToArray());
如您所见,我在某些时候添加了对额外程序集的引用。出于某种原因,当我将 using System.Net;
添加到文本文件时,它不会被引用并且出现错误。我正在编译的文本实际上是一个保存为文本的 .cs 文件。我想通过提取 using *
并单独添加它们来解决这个问题,但是当添加 System.Net.Mail.dll
时,找不到元数据文件。
有没有人经历过类似的事情?我真的很想将 using *
添加到文件中并准备好。
任何输入将不胜感激。
这里的问题是 System.Net.dll
不存在。您可以通过右键单击它被引用的某处并选择 "Go to definition" 来检查 .Net 类型在哪个程序集中。这将打开一个带有 class 定义 "from metadata" 的选项卡。在此文件的顶部,您有一个 #region
显示此类型的来源。在 TcpClient
的情况下,我们可以看到:
#region Assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.dll
#endregion
将您对 Compile
的调用更改为 "System.dll" 而不是 "System.Net.dll",它应该可以正常工作
Edit/Clarification: 无法从 using
语句中获取程序集名称。
我在运行时将文本编译成动态对象时遇到问题。
我写了一段简单的代码编译文案:
public class CompileFactory
{
public dynamic Compile(String classCode, String mainClass, Object[] requiredAssemblies)
{
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string>
{
{ "CompilerVersion", "v4.0" }
});
CompilerParameters parameters = new CompilerParameters
{
GenerateExecutable = true, // Create a dll
GenerateInMemory = true, // Create it in memory
WarningLevel = 3, // Default warning level
CompilerOptions = "/optimize", // Optimize code
TreatWarningsAsErrors = false // Better be false to avoid break in warnings
};
// Add all extra assemblies required
foreach (var extraAsm in requiredAssemblies)
{
parameters.ReferencedAssemblies.Add(extraAsm as string);
}
CompilerResults results = provider.CompileAssemblyFromSource(parameters, classCode);
if (results.Errors.Count != 0)
{
return "FAILED";
}
return results.CompiledAssembly.CreateInstance(mainClass); ;
}
}
这就是我使用 Compile
方法的方式。
List<string> assemblies = new List<string>{"System.Net.Mail.dll", "System.Net.dll"};
dynamic obj = compile.Compile(fileText, pluginName, assemblies.ToArray());
如您所见,我在某些时候添加了对额外程序集的引用。出于某种原因,当我将 using System.Net;
添加到文本文件时,它不会被引用并且出现错误。我正在编译的文本实际上是一个保存为文本的 .cs 文件。我想通过提取 using *
并单独添加它们来解决这个问题,但是当添加 System.Net.Mail.dll
时,找不到元数据文件。
有没有人经历过类似的事情?我真的很想将 using *
添加到文件中并准备好。
任何输入将不胜感激。
这里的问题是 System.Net.dll
不存在。您可以通过右键单击它被引用的某处并选择 "Go to definition" 来检查 .Net 类型在哪个程序集中。这将打开一个带有 class 定义 "from metadata" 的选项卡。在此文件的顶部,您有一个 #region
显示此类型的来源。在 TcpClient
的情况下,我们可以看到:
#region Assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.dll
#endregion
将您对 Compile
的调用更改为 "System.dll" 而不是 "System.Net.dll",它应该可以正常工作
Edit/Clarification: 无法从 using
语句中获取程序集名称。