[英]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.