C#动态代码中无法创建EA_Netzteil类实例的问题求助
解决动态编译代码无法找到EA_Netzteil类的问题
这个问题的核心原因很明确:动态编译的代码运行在一个全新的内存程序集里,默认不会引用你的宿主程序集(也就是包含EA_Netzteil类的那个程序集),而常规类因为和EA_Netzteil在同一个程序集,所以能正常找到它。
下面是具体的解决步骤和代码修改方案:
步骤1:添加宿主程序集的引用
你需要在动态编译的参数中,明确添加对包含EA_Netzteil类的程序集的引用。最可靠的方式是通过typeof(EA_Netzteil)来获取该类所在的程序集路径,避免硬编码路径出错。
方案A:直接在CodeHelper中添加引用(推荐)
修改CodeHelper.HelperFunction方法,在添加基础引用的代码块后,加入对宿主程序集的引用:
// ------------ // Add basic referenced assemblies parameters.ReferencedAssemblies.Add("system.dll"); parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll"); parameters.ReferencedAssemblies.Add("System.Core.dll"); // 添加包含EA_Netzteil的程序集引用 parameters.ReferencedAssemblies.Add(typeof(EA_Netzteil).Assembly.Location); // ------------
方案B:通过requiredAssemblies参数传递
如果你想保持HelperFunction的灵活性,可以在调用时传入程序集路径:
修改Execute方法中的requiredAssemblies定义:
// 获取包含EA_Netzteil的程序集路径 string hostAssemblyPath = typeof(EA_Netzteil).Assembly.Location; Object[] requiredAssemblies = new Object[] { hostAssemblyPath };
步骤2:确认命名空间匹配(已满足,可跳过)
你动态生成的代码已经在Testumgebung命名空间下,和EA_Netzteil的命名空间一致,所以不需要额外添加using Testumgebung;指令。如果后续类的命名空间有变化,记得同步调整动态代码的命名空间或者添加using指令。
修改后的完整CodeHelper类示例
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.CSharp; using System.CodeDom.Compiler; using System.Reflection; using System.Reflection.Emit; namespace Testumgebung { public class CodeHelper { public static object HelperFunction(String classCode, String mainClass, Object[] requiredAssemblies) { CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } }); CompilerParameters parameters = new CompilerParameters { GenerateExecutable = false, // 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 basic referenced assemblies parameters.ReferencedAssemblies.Add("system.dll"); parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll"); parameters.ReferencedAssemblies.Add("System.Core.dll"); // 添加包含EA_Netzteil的程序集引用 parameters.ReferencedAssemblies.Add(typeof(EA_Netzteil).Assembly.Location); //---------------- // Add all extra assemblies required foreach (var extraAsm in requiredAssemblies) { parameters.ReferencedAssemblies.Add(extraAsm as string); } //-------------------- // Try to compile the code received CompilerResults results = provider.CompileAssemblyFromSource(parameters, classCode); //-------------------- // If the compilation returned error, then return the CompilerErrorCollection class // with the errors to the caller if (results.Errors.Count != 0) { return results.Errors; } //-------------------- // Return the created class instance to caller return results.CompiledAssembly.CreateInstance(mainClass); ; } } }
为什么这样能解决问题?
动态编译的CSharpCodeProvider默认只会引用你显式指定的程序集。通过添加宿主程序集的引用,动态编译的编译器就能找到EA_Netzteil类的定义,和常规类的运行环境保持一致。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

