我正在使用CodeDOM在运行时创建内存中的程序集,如下所示:
public Assembly Compile(CodeCompileUnit targetUnit)
{
string path = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath);
var compilerParameters = new CompilerParameters
{
GenerateInMemory = true,
IncludeDebugInformation = true,
TreatWarningsAsErrors = true,
WarningLevel = 4,
CompilerOptions = "/nostdlib",
};
//For system.dll
compilerParameters.ReferencedAssemblies.Add(typeof(System.Diagnostics.Debug).Assembly.Location);
//For system.core.dll
compilerParameters.ReferencedAssemblies.Add(typeof(System.IO.DirectoryInfo).Assembly.Location);
//For Microsoft.CSharp.dll
compilerParameters.ReferencedAssemblies.Add(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.Location);
compilerParameters.ReferencedAssemblies.Add(typeof(System.Runtime.CompilerServices.CallSite).Assembly.Location);
//Add other assemblies as needed.
var compilerResults = new CSharpCodeProvider()
.CompileAssemblyFromDom(compilerParameters, targetUnit);
if (compilerResults == null)
{
throw new InvalidOperationException("ClassCompiler did not return results.");
}
if(compilerResults.Errors.HasErrors)
{
var errors = string.Empty;
foreach (CompilerError compilerError in compilerResults.Errors)
{
errors += compilerError.ErrorText + "\n";
}
Debug.Fail(errors);
throw new InvalidOperationException("Errors occured while compiling dynamic classes:\n" + errors);
}
var dynamicAssembly = compilerResults.CompiledAssembly;
return dynamicAssembly;
}
上面生成的程序集在ASPNET主机启动时添加到BuildManager中:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyWebApp.MyStartup), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(MyWebApp.MyStartup), "Stop")]
namespace MyWebApp
{
public static class MyStartup
{
public static void Start()
{
System.Reflection.Assembly assembly = GetDynamicAssembly();
System.Web.Compilation.BuildManager.AddReferencedAssembly(assembly);
}
private static System.Reflection.Assembly GetDynamicAssembly()
{
//create and return dynamic assemblies using Codedom here
var unit = GetCompilationUnit(); //elided for brevity
return Compile(unit);
}
public static void Stop()
{
//do cleanup if needed
}
}
}
上述工作主要是,但有时,我一直收到以下错误,没有明确的原因指示:
[NullReferenceException: Object reference not set to an instance of an object.]
System.CodeDom.Compiler.CodeDomProvider.TryGetProbableCoreAssemblyFilePath(CompilerParameters parameters, String& coreAssemblyFilePath) +245
Microsoft.CSharp.CSharpCodeGenerator.CmdArgsFromParameters(CompilerParameters options) +149
Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames) +366
Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, String[] fileNames) +160
System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromFile(CompilerParameters options, String[] fileNames) +23
System.Web.Compilation.AssemblyBuilder.Compile() +884
System.Web.Compilation.BuildProvidersCompiler.PerformBuild() +9519768
System.Web.Compilation.ApplicationBuildProvider.GetGlobalAsaxBuildResult(Boolean isPrecompiledApp) +9929000
System.Web.Compilation.BuildManager.CompileGlobalAsax() +44
System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +269
[HttpException (0x80004005): Object reference not set to an instance of an object.]
System.Web.Compilation.BuildManager.ReportTopLevelCompilationException() +62
System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +427
System.Web.Compilation.BuildManager.CallAppInitializeMethod() +31
System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +535
[HttpException (0x80004005): Object reference not set to an instance of an object.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9930508
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +101
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254
我查看了csharpcodeprovider中 CmdArgsFromParamters 的来源 调用 TryGetProbableCoreAssemblyFilePath ,它似乎正在寻找 CoreAssemblyFileName :
string coreAssemblyFileName = options.CoreAssemblyFileName;
if (String.IsNullOrWhiteSpace(options.CoreAssemblyFileName)) {
string probableCoreAssemblyFilePath;
if(CodeDomProvider.TryGetProbableCoreAssemblyFilePath(options, out probableCoreAssemblyFilePath)) {
coreAssemblyFileName = probableCoreAssemblyFilePath;
}
我是否需要明确设置 CoreAssemblyFileName ,如果是,应该将其设置为什么?关于此的文档似乎有点稀疏。
重申一下,上述错误会间歇性地发生,我很困惑,因为根本原因是什么?