在运行时编译代码,加载到当前appdomain但Type.GetType无法看到它

我在运行时编译一些代码,然后将程序集加载到当前的appdomain,但是当我尝试做Type.GetType时,它无法找到类型…

以下是我编译代码的方法……

public static Assembly CompileCode(string code) { Microsoft.CSharp.CSharpCodeProvider provider = new CSharpCodeProvider(); ICodeCompiler compiler = provider.CreateCompiler(); CompilerParameters compilerparams = new CompilerParameters(); compilerparams.GenerateExecutable = false; compilerparams.GenerateInMemory = false; foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { string location = assembly.Location; if (!String.IsNullOrEmpty(location)) { compilerparams.ReferencedAssemblies.Add(location); } } catch (NotSupportedException) { // this happens for dynamic assemblies, so just ignore it. } } CompilerResults results = compiler.CompileAssemblyFromSource(compilerparams, code); if (results.Errors.HasErrors) { StringBuilder errors = new StringBuilder("Compiler Errors :\r\n"); foreach (CompilerError error in results.Errors) { errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText); } throw new Exception(errors.ToString()); } else { AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName()); return results.CompiledAssembly; } } 

从编译的程序集中获取类型后该位失败就好了,它似乎无法使用Type.GetType找到它….

 Assembly assem = RuntimeCodeCompiler.CompileCode(code); string typeName = String.Format("Peverel.AppFramework.Web.GenCode.ObjectDataSourceProxy_{0}", safeTypeName); Type t = assem.GetType(typeName); //This works just fine.. Type doesntWork = Type.GetType(t.AssemblyQualifiedName); Type doesntWork2 = Type.GetType(t.Name); .... 

找到了这个很好的代码,确保无论你如何加载你的程序集,它总是可以从Type.GetType中获得。

我的用于将代码编译到当前appdomain的类现在看起来像:

 public static class RuntimeCodeCompiler { private static volatile Dictionary cache = new Dictionary(); private static object syncRoot = new object(); static Dictionary assemblies = new Dictionary(); static RuntimeCodeCompiler() { AppDomain.CurrentDomain.AssemblyLoad += (sender, e) => { assemblies[e.LoadedAssembly.FullName] = e.LoadedAssembly; }; AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => { Assembly assembly = null; assemblies.TryGetValue(e.Name, out assembly); return assembly; }; } public static Assembly CompileCode(string code) { Microsoft.CSharp.CSharpCodeProvider provider = new CSharpCodeProvider(); ICodeCompiler compiler = provider.CreateCompiler(); CompilerParameters compilerparams = new CompilerParameters(); compilerparams.GenerateExecutable = false; compilerparams.GenerateInMemory = false; foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { string location = assembly.Location; if (!String.IsNullOrEmpty(location)) { compilerparams.ReferencedAssemblies.Add(location); } } catch (NotSupportedException) { // this happens for dynamic assemblies, so just ignore it. } } CompilerResults results = compiler.CompileAssemblyFromSource(compilerparams, code); if (results.Errors.HasErrors) { StringBuilder errors = new StringBuilder("Compiler Errors :\r\n"); foreach (CompilerError error in results.Errors) { errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText); } throw new Exception(errors.ToString()); } else { AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName()); return results.CompiledAssembly; } } public static Assembly CompileCodeOrGetFromCache(string code, string key) { bool exists = cache.ContainsKey(key); if (!exists) { lock (syncRoot) { exists = cache.ContainsKey(key); if (!exists) { cache.Add(key, CompileCode(code)); } } } return cache[key]; } } 

你应该阅读更多关于程序集加载,类型解析,…我不知道为什么你的代码完全可以工作,但我猜你有以下问题:

编译程序集然后调用AppDomain.CurrentDomain.Load来加载程序集。 但是你没有返回刚加载的程序集。 从编译结果返回程序集。 现在您有两个相同程序集的实例,并且您从该程序集中获得两次类型。 这些对具有相同的名称,但它们的类型不同!