使用CodeDOM将程序集添加到BuildManager导致间歇性错误

时间:2015-01-30 07:26:11

标签: c# asp.net-mvc codedom base-class-library

我正在使用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 ,如果是,应该将其设置为什么?关于此的文档似乎有点稀疏。

重申一下,上述错误会间歇性地发生,我很困惑,因为根本原因是什么?

0 个答案:

没有答案