简体   繁体   English

为什么连接调试器时,即时编译的C#代码不起作用?

[英]Why does C# code compiled on the fly not work when a debugger is attached?

I have the following C# project targetting .NET 4.0 that takes a source code file, compiles it into an assembly on the fly and then executes a static method of a type contained in that assembly. 我有以下C#项目,目标是.NET 4.0,它接受源代码文件,动态地将其编译成一个程序集,然后执行该程序集中包含的类型的静态方法。

This works as expected, as long as I don't start the program with a debugger attached. 这可以按预期工作,只要我没有附加调试器启动程序。 In that case I get an exception on the call to xmlSerializer.Serialize(sw, family); 在这种情况下,我在调用xmlSerializer.Serialize(sw, family);遇到异常xmlSerializer.Serialize(sw, family); , more precisely a System.NullReferenceException inside a System.TypeInitializationException inside a System.InvalidOperationException . 更确切地说, System.InvalidOperationException内的System.TypeInitializationException内的System.NullReferenceException

If I take the same program, include the source code file in the project and compile it directly into the main program assembly, I will not get an exception regardless of whether or not a debugger is attached. 如果我采用相同的程序,在项目中包含源代码文件并将其直接编译到主程序集中,无论是否附加调试器,我都不会得到异常。

Please note that I my project references the exact same assemblies as those listed when compiling on the fly. 请注意,我的项目引用了与动态编译时列出的完全相同的程序集。

Why does it matter to the code compiled on the fly whether or not a debugger is attached? 无论调试器是否附加,为什么动态编译的代码都很重要? What am I missing? 我错过了什么?

Main file Program.cs : 主文件Program.cs

using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;
using System.Linq;

namespace DebugSerializeCompiler
{
    class Program
    {
        static void Main()
        {
            if (!Environment.GetCommandLineArgs().Contains("Compile"))
            {
                DebugSerializeCompiler.SerializerTest.Run();
            }
            else
            {
                Assembly assembly;
                if (TryCompile("..\\..\\SerializerTest.cs", new[]{ "Microsoft.CSharp.dll",
                   "System.dll", "System.Core.dll", "System.Data.dll", "System.Xml.dll" }, 
                   out assembly))
                {
                    Type type = assembly.GetType("DebugSerializeCompiler.SerializerTest");
                    MethodInfo methodInfo = type.GetMethod("Run");
                    methodInfo.Invoke(null, null);
                }
            }
            Console.ReadKey();
        }

        static bool TryCompile(string fileName, string[] referencedAssemblies, 
           out Assembly assembly)
        {
            bool result;

            CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
            var compilerparams = new CompilerParameters 
                                     {
                                        GenerateExecutable = false, 
                                        GenerateInMemory = true
                                     };
            foreach (var referencedAssembly in referencedAssemblies)
            {
                compilerparams.ReferencedAssemblies.Add(referencedAssembly);
            }

            using (var reader = new StreamReader(fileName))
            {
                CompilerResults compilerResults = 
                   compiler.CompileAssemblyFromSource(compilerparams, reader.ReadToEnd());
                assembly = compilerResults.CompiledAssembly;
                result = !compilerResults.Errors.HasErrors;
                if (!result)
                {
                    Console.Out.WriteLine("Compiler Errors:");
                    foreach (CompilerError error in compilerResults.Errors)
                    {
                        Console.Out.WriteLine("Position {0}.{1}: {2}", 
                           error.Line, error.Column, error.ErrorText);
                    }
                }
            }

            return result;
        }
    }
}

File compiled into separate assembly SerializerTest.cs : 文件编译成单独的程序集SerializerTest.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace DebugSerializeCompiler
{
    public  class SerializerTest
    {
        public static void Run()
        {
            Console.WriteLine("Executing Run()");
            var family = new Family();
            var xmlSerializer = new XmlSerializer(typeof(Family));

            TextWriter sw = new StringWriter();
            try
            {
                if (sw == null) Console.WriteLine("sw == null");
                if (family == null) Console.WriteLine("family == null");
                if (xmlSerializer == null) Console.WriteLine("xmlSerializer == null");
                xmlSerializer.Serialize(sw, family);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception caught:");
                Console.WriteLine(e);
            }
            Console.WriteLine(sw);
        }
    }

    [Serializable]
    public class Family
    {
        public string LastName { get; set; }

        public List<FamilyMember> FamilyMembers { get; set; }
    }

    [Serializable]
    public class FamilyMember
    {
        public string FirstName { get; set; }
    }
}

This is the csproj file used to compile the project using Visual C# 2010 Express on Windows 7: 这是用于在Windows 7上使用Visual C#2010 Express编译项目的csproj文件:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{7B8D2187-4C58-4310-AC69-9F87107C25AA}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>DebugSerializeCompiler</RootNamespace>
    <AssemblyName>DebugSerializeCompiler</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <PlatformTarget>x86</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="SerializerTest.cs">
      <SubType>Code</SubType>
    </Compile>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

It worked fine for me. 它对我来说很好。

But if I had to guess what's going on for you it would be that because you're compiling the class in with your main project and dynamically compiling it the serializer is getting confused about which assembly to use and is failing. 但是,如果我不得不猜测你发生了什么,那就是因为你正在用你的主项目编译类并动态编译它,序列化器会对使用哪个程序集而失败感到困惑。 You could try attaching an event to AppDomain.CurrentDomain.AssemblyResolve and see if there are any assemblies failing to resolve there. 您可以尝试将事件附加到AppDomain.CurrentDomain.AssemblyResolve并查看是否有任何程序集无法在那里解析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么当我使用 !!= C# 时代码会被编译 - Why does the code get compiled when I use !!= C# 附加调试器的 C# 代码非常慢; MemoryMappedFile 的错? - C# code very slow with debugger attached; MemoryMappedFile's fault? 为什么以下C#多线程代码虽然在调试器中没有输出零? - Why the following C# multi-threaded code does not output zero though it does in debugger? 为什么我的 C# Xml 代码仅在我枚举变量可枚举时才有效 - Why does my C# Xml code only work when I enumerate variable enumerable 为什么只有在C#中创建/运行表单时某些代码才起作用? - Why does some code only work when I create/run a form in C#? 使用 VS Code 在 C# 中调试 xUnit 测试时,调试器不会启动 - Debugger does not launch when debugging xUnit tests in C# with VS Code 如果C#代码是JIT编译的,为什么我在构建时必须在Visual Studio中选择目标平台? - If C# code is JIT compiled why do I have to choose a target platform in Visual Studio when building? 为什么此C#代码无法运行可执行文件? - Why does this C# code to run executables not work? 为什么我的C#Windows窗体中的代码不起作用? - Why does my code in my c# windows form not work? 为什么TcpClient的此代码在vb.net中有效,而在c#中却无效? - Why does this code for TcpClient work in vb.net, but not c#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM