Ric*_*end 5 .net c# asp.net compiler-construction reflection
我在运行时编译一些代码,然后将程序集加载到当前的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;
}
}
Run Code Online (Sandbox Code Playgroud)
从编译的程序集中获取类型后这个位失败就好了,它似乎无法使用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);
....
Run Code Online (Sandbox Code Playgroud)
找到了这个很好的代码,确保无论你如何加载你的程序集,它总是可以从Type.GetType中获得.
我将类编译到当前appdomain的类现在看起来像:
public static class RuntimeCodeCompiler
{
private static volatile Dictionary<string, Assembly> cache = new Dictionary<string, Assembly>();
private static object syncRoot = new object();
static Dictionary<string, Assembly> assemblies = new Dictionary<string, Assembly>();
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];
}
}
Run Code Online (Sandbox Code Playgroud)