2012-02-15 28 views
10

Tôi có C# dự án nhắm mục tiêu .NET 4.0 sau đây có một tệp mã nguồn, biên dịch nó thành một assembly ngay lập tức và sau đó thực hiện một phương thức tĩnh của một kiểu chứa trong assembly đó.Tại sao mã C# được biên dịch khi không hoạt động khi trình gỡ lỗi được đính kèm?

Điều này hoạt động như mong đợi, miễn là tôi không khởi động chương trình bằng trình gỡ lỗi được đính kèm. Trong trường hợp đó, tôi nhận được một ngoại lệ về cuộc gọi đến xmlSerializer.Serialize(sw, family);, chính xác hơn là System.NullReferenceException bên trong một System.TypeInitializationException bên trong một System.InvalidOperationException.

Nếu tôi thực hiện cùng một chương trình, bao gồm tệp mã nguồn trong dự án và biên dịch trực tiếp vào hội đồng chương trình chính, tôi sẽ không nhận được ngoại lệ cho dù có đính kèm trình gỡ rối hay không.

Xin lưu ý rằng tôi dự án của tôi tham chiếu chính xác cùng một cụm như những người được liệt kê khi biên dịch khi đang bay.

Tại sao mã quan trọng được biên dịch khi đang chạy có hay không trình gỡ rối được đính kèm? Tôi đang thiếu gì?

tập tin Main 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 biên dịch vào lắp ráp riêng 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; } 
    } 
} 

Đây là tập tin csproj sử dụng để lập dự án sử dụng Visual C# 2010 Express trên Windows 7:

<?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> 
+0

Vậy đối tượng nào là rỗng? –

+0

@Ramhound Câu hỏi hay. Chắc chắn không có đối tượng nào của tôi là null. Tôi chỉ cần thêm một kiểm tra để làm rõ điều đó. – PersonalNexus

+0

Bạn cũng có thể thử sử dụng bản xem trước Roslyn và xem bạn có may mắn hơn với CodeDom hay không. Có những công cụ khác làm những việc tương tự như vậy, chẳng hạn như trình biên dịch đơn như là một máy chủ và NRefactory ... Các codedom khá nhiều sucks. –

Trả lời

2

Nó hoạt động tốt cho tôi. Nhưng nếu tôi phải đoán xem điều gì đang xảy ra với bạn thì đó là vì bạn đang biên dịch lớp với dự án chính của bạn và biên dịch động nó serializer đang bị nhầm lẫn về việc lắp ráp nào sử dụng và không thành công. Bạn có thể thử gắn một sự kiện vào AppDomain.CurrentDomain.AssemblyResolve và xem có bất kỳ hội đồng nào không giải quyết được sự kiện đó không.

+0

Bạn đang sử dụng IDE và phiên bản nào? Phiên bản khung này là gì? Tôi đang sử dụng VS 2008 SP1 trên win7 và mã của bạn đang chạy được biên dịch như là không có bất kỳ vấn đề. Nó hoạt động tương tự cho tôi có hoặc không có trình gỡ rối đính kèm. Bạn có bất kỳ phần mở rộng nào, chẳng hạn như R #? Bạn có thể hiển thị tệp .csproj không? Bạn có thể có một cái gì đó kỳ lạ xảy ra trong cách bạn đang biên dịch dự án. –

+0

Đây là nó. Trong trình xử lý sự kiện 'AppDomain.CurrentAppDomain.AssemblyResolve' tôi nhận được một yêu cầu cho assembly được biên dịch nhanh chóng, nhưng chỉ khi chạy dưới trình gỡ rối. Khi tôi lưu assembly trong một trường '_assembly' sau khi biên dịch và trả về khi tên assembly được yêu cầu khớp với tên của assembly được biên dịch trong trình xử lý sự kiện, nó hoạt động ngay cả với trình gỡ lỗi đính kèm. Tôi thực sự muốn biết tại sao mà làm cho một sự khác biệt, mặc dù. – PersonalNexus

+0

Đó là .NET 4.0 và tôi đã thử với Visual Studio 2010 Premium cũng như Visual Studio 2010 Express Edition (không có phần mở rộng) với một dự án Ứng dụng Console chuẩn và không có thay đổi đối với bất kỳ cài đặt IDE hoặc trình gỡ lỗi nào. Tôi sẽ bao gồm tệp .csproj trong câu hỏi. – PersonalNexus

Các vấn đề liên quan