青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Programmer's Cookbook

{C++ 基礎(chǔ)} {C++ 高級(jí)} {C#界面,C++核心算法} {設(shè)計(jì)模式} {C#基礎(chǔ)}

XmlSerializer 常見(jiàn)問(wèn)題疑難解答

http://www.microsoft.com/china/MSDN/library/data/xml/Usdnxmlnettrblshtxsd.mspx?mfr=true


XmlSerializer 常見(jiàn)問(wèn)題疑難解答

發(fā)布日期: 6/30/2004 | 更新日期: 6/30/2004

Christoph Schittko

適用于:
Microsoft ?Visual Studio ?.NET

摘要:Christoph Schittko 討論了各種相關(guān)技巧,以便診斷在使用 .NET 框架中的 XML 序列化技術(shù)將 XML 轉(zhuǎn)換為對(duì)象(以及反向轉(zhuǎn)換)時(shí)發(fā)生的常見(jiàn)問(wèn)題。

*
本頁(yè)內(nèi)容
簡(jiǎn)介 簡(jiǎn)介
XmlSerializer 的內(nèi)部工作方式 XmlSerializer 的內(nèi)部工作方式
序列化錯(cuò)誤 序列化錯(cuò)誤
聲明序列化類型 聲明序列化類型
反序列化 XML 時(shí)發(fā)生的問(wèn)題 反序列化 XML 時(shí)發(fā)生的問(wèn)題
來(lái)自構(gòu)造函數(shù)的異常 來(lái)自構(gòu)造函數(shù)的異常
小結(jié) 小結(jié)
致謝 致謝

簡(jiǎn)介

.NET 框架中的 XmlSerializer 是一種很棒的工具,它將高度結(jié)構(gòu)化的 XML 數(shù)據(jù)映射到 .NET 對(duì)象。XmlSerializer 在程序中通過(guò)單個(gè) API 調(diào)用來(lái)執(zhí)行 XML 文檔和對(duì)象之間的轉(zhuǎn)換。轉(zhuǎn)換的映射規(guī)則在 .NET 類中通過(guò)元數(shù)據(jù)屬性來(lái)表示。這一編程模型帶有自己的錯(cuò)誤類別,開(kāi)發(fā)人員需要了解如何診斷這些錯(cuò)誤。例如,元數(shù)據(jù)屬性必須描述序列化程序可以處理的 XML 格式的所有變體。本文研究了在使用 XmlSerializer 構(gòu)建基于 XML 的解決方案時(shí)可能發(fā)生的各種錯(cuò)誤,并且討論了用來(lái)診斷這些錯(cuò)誤的技巧和工具。

XmlSerializer 的內(nèi)部工作方式

為了有效地解決在 XML 序列化過(guò)程中出現(xiàn)的問(wèn)題,需要了解一下在非常簡(jiǎn)單的 XmlSerializer 接口的內(nèi)部發(fā)生了什么事情。與傳統(tǒng)的分析范型相反,.NET 框架中 System.Xml.Serialization 命名空間的 XmlSerializer 將 XML 文檔綁定到 .NET 類的實(shí)例。程序員不再需要編寫(xiě) DOM 或 SAX 分析代碼,而是通過(guò)直接在這些類中附加 .NET 元數(shù)據(jù)屬性來(lái)聲明性地設(shè)置綁定規(guī)則。因?yàn)樗蟹治鲆?guī)則都是通過(guò)屬性表示的,所以 XmlSerializer 的接口非常簡(jiǎn)單。它主要由兩個(gè)方法組成:Serialize() 用于從對(duì)象實(shí)例生成 XML;Deserialize() 用于將 XML 文檔分析成對(duì)象圖。

在使用強(qiáng)類型的、能夠完美地映射到編程對(duì)象的結(jié)構(gòu)嚴(yán)謹(jǐn)?shù)?XML 格式時(shí),這種方法非常有效。如果格式由 W3C架構(gòu)定義,并且該架構(gòu)由不帶混合型內(nèi)容或且不過(guò)度使用通配符(xs:any 和 xs;anyAttribute)的 complexType 組成,則 XML 序列化是處理該數(shù)據(jù)的好方法。

面向消息的應(yīng)用程序就是一個(gè)很好的例子,這些應(yīng)用程序之間的交換格式已預(yù)先定義。因?yàn)樵S多消息驅(qū)動(dòng)的企業(yè)應(yīng)用程序都具有非常高的吞吐量要求,所以 Serialize() 和 Deserialize() 方法被設(shè)計(jì)為具有很高的執(zhí)行速度。實(shí)際上,正是 XmlSerializer 為 System.Messaging 命名空間中的具有高度可伸縮性的庫(kù)、ASP.NET Web 服務(wù) BizTalk Server 2004 提供了動(dòng)力。

為獲得 XmlSerializer 的高性能,需要付出雙重代價(jià)。首先是與給定 XmlSerializer 可以處理的 XML 格式有關(guān)的靈活性,其次是實(shí)例的構(gòu)造需要進(jìn)行大量的處理。

當(dāng)您實(shí)例化 XmlSerializer 時(shí),必須傳遞您試圖通過(guò)該序列化程序?qū)嵗M(jìn)行序列化和反序列化的對(duì)象的類型。序列化程序?qū)z查該類型的所有公共字段和屬性,以了解一個(gè)實(shí)例在運(yùn)行時(shí)引用哪些類型。接下來(lái),它將為一組類創(chuàng)建 C# 代碼,以便使用 System.CodeDOM 命名空間中的類處理序列化和反序列化。在此過(guò)程中,XmlSerializer 將檢查 XML 序列化屬性的反射類型,以便根據(jù) XML 格式定義來(lái)自定義所創(chuàng)建的類。這些類隨后被編譯為臨時(shí)程序集,并由 Serialize() 和 Deserialize() 方法調(diào)用以執(zhí)行 XML 到對(duì)象的轉(zhuǎn)換。

這個(gè)設(shè)置 XmlSerializer 的精巧過(guò)程和聲明性編程模型導(dǎo)致了三類錯(cuò)誤,其中一些錯(cuò)誤可能很難解決:

?

所生成的序列化類期望被序列化的對(duì)象完全符合元數(shù)據(jù)屬性所定義的類型結(jié)構(gòu)。如果 XmlSerializer 遇到未聲明(顯式聲明或者是通過(guò) XML 序列化屬性聲明)的類型,則對(duì)象將無(wú)法序列化。

?

XML 文檔在以下情況下無(wú)法反序列化:該文檔的根元素不能映射對(duì)象類型;該文檔的格式不正確,例如包含 XML 規(guī)范中定義為非法的字符;該文檔違反基礎(chǔ)架構(gòu)的限制(在某些情形下)。

?

最后,序列化類的創(chuàng)建及其隨后的編譯可能由于多種不同的原因而失敗。當(dāng)傳遞給構(gòu)造函數(shù)的類型或者由該類型引用的類型實(shí)現(xiàn)了不受支持的接口或者不能滿足 XmlSerializer 施加的限制時(shí),類的創(chuàng)建可能會(huì)失敗。

當(dāng)附加的屬性生成無(wú)法編譯的 C# 代碼時(shí),編譯步驟可能會(huì)失敗。編譯步驟也可能由于與安全有關(guān)的原因而失敗。

下面各個(gè)部分將更深入地研究這些情況,并提供有關(guān)如何解決這些問(wèn)題的指導(dǎo)和建議。

序列化錯(cuò)誤

我們要研究的第一類錯(cuò)誤發(fā)生在 Serialize() 方法中。當(dāng)在運(yùn)行時(shí)傳遞給該方法的對(duì)象圖中的類型與在設(shè)計(jì)時(shí)在類中聲明的類型不匹配時(shí),將發(fā)生此類錯(cuò)誤。您可以通過(guò)字段或?qū)傩缘念愋投x來(lái)隱式聲明類型,也可以通過(guò)附加序列化屬性來(lái)顯式聲明類型。

typedecl

1. 對(duì)象圖中的類型聲明

這里需要指出的是,依靠繼承是不夠的。開(kāi)發(fā)人員必須通過(guò)將 XmlInclude 屬性附加到基類,或者通過(guò)將 XmlElement 屬性附加到字段(這些字段可以容納從所聲明的類型派生的類型的對(duì)象),來(lái)聲明 XmlSerializer 的派生類型。

例如,請(qǐng)看一下以下類層次結(jié)構(gòu):

public class Base
{
   public string Field;
}
public class Derived
{
  public string AnotherField;
}
public class Container
{
  public Base MyField;
}
如果您依賴?yán)^承并且編寫(xiě)了與下面類似的序列化代碼:
Container obj = new Container();
obj.MyField = new Derived(); // legal assignment in the 
                             //.NET type system
// ...
XmlSerializer serializer = new XmlSerializer( typeof( Container ) );
serializer.Serialize( writer, obj ); // Kaboom!

您將得到發(fā)自 Serialize() 方法的異常,這是因?yàn)闆](méi)有 XmlSerializer 的顯式類型聲明。

發(fā)自 XmlSerializer 的異常

診斷這些問(wèn)題的根源在開(kāi)始時(shí)可能比較困難,這是因?yàn)閬?lái)自 XmlSerializer 的異??雌饋?lái)并沒(méi)有提供有關(guān)其產(chǎn)生原因的大量信息;至少,它們沒(méi)有在開(kāi)發(fā)人員通常會(huì)查看的地點(diǎn)提供信息。

在大多數(shù)情況下,當(dāng)發(fā)生錯(cuò)誤時(shí),Serialize、Deserialize 甚至 XmlSerializer 構(gòu)造函數(shù)都會(huì)引發(fā)一個(gè)相當(dāng)普通的 System.InvalidOperationException。該異常類型可以在 .NET 框架中的許多地方出現(xiàn);它根本不是 XmlSerializer 所特有的。更糟糕的是,該異常的 Message 屬性也僅產(chǎn)生非常普通的信息。在上述示例中,Serialize() 方法會(huì)引發(fā)帶有以下消息的異常:

There was an error generating the XML document.

該消息最多也就是令人討厭的,因?yàn)楫?dāng)您看到 XmlSerializer 引發(fā)異常時(shí),就已經(jīng)猜到了這一點(diǎn)。現(xiàn)在,您只好無(wú)奈地發(fā)現(xiàn)該異常的 Message 無(wú)法幫助您解決問(wèn)題。

奇怪的異常消息和非描述性的異常類型反映了本文前面介紹的 XmlSerializer 內(nèi)部工作方式。Serialize() 方法會(huì)捕獲序列化類中引發(fā)的所有異常,將它們包裝到 InvalidOperationException 中,然后將該異常包沿著堆棧向上傳遞。

讀取異常消息

得到“實(shí)際”的異常信息的竅門是檢查該異常的 InnerException 屬性。InnerException 引用了從序列化類內(nèi)部引發(fā)的實(shí)際異常。它包含有關(guān)該問(wèn)題及其發(fā)生地點(diǎn)的非常詳細(xì)的信息。您在運(yùn)行上述示例時(shí)捕獲的異常將包含帶有以下消息的 InnerException:

The type Derived was not expected. Use the XmlInclude or SoapInclude 
attribute to specify types that are not known statically.

您可以通過(guò)直接檢查 InnerException 或者通過(guò)調(diào)用該異常的 ToString() 方法來(lái)得到此消息。下面的代碼片段演示了一個(gè)異常處理程序,它寫(xiě)出了在反序列化對(duì)象的過(guò)程中發(fā)生的所有異常中的信息:

public void SerializeContainer( XmlWriter writer, Container obj )
{
  try
  {
    // Make sure even the construsctor runs inside a
    // try-catch block
    XmlSerializer ser = new XmlSerializer( typeof(Container));
    ser.Serialize( writer, obj );
  }
  catch( Exception ex )               
  {                                   
    DumpException( ex );             
  }                                   
}
public static void DumpException( Exception ex )
{
  Console.WriteLine( "--------- Outer Exception Data ---------" );        
  WriteExceptionInfo( ex );
  ex = ex.InnerException;                     
  if( null != ex )               
  {                                   
    Console.WriteLine( "--------- Inner Exception Data ---------" );                
    WriteExceptionInfo( ex.InnerException );    
    ex = ex.InnerException;
  }
}
public static void WriteExceptionInfo( Exception ex )
{
  Console.WriteLine( "Message: {0}", ex.Message );                  
  Console.WriteLine( "Exception Type: {0}", ex.GetType().FullName );
  Console.WriteLine( "Source: {0}", ex.Source );                    
  Console.WriteLine( "StrackTrace: {0}", ex.StackTrace );           
  Console.WriteLine( "TargetSite: {0}", ex.TargetSite );            
}

聲明序列化類型

要解決上述示例中的問(wèn)題,您只需讀取 InnerException 的消息并實(shí)現(xiàn)建議的解決方案。傳遞給 Serialize 方法的對(duì)象圖中的一個(gè)字段引用了一個(gè)類型為 Derived 的對(duì)象,但并未將該字段聲明為序列化 Derived 類型的對(duì)象。盡管該對(duì)象圖在 .NET 類型系統(tǒng)中完全合法,但 XmlSerializer 的構(gòu)造函數(shù)在遍歷容器類型的字段時(shí),并不知道為 Derived 類型的對(duì)象創(chuàng)建了序列化代碼,這是因?yàn)樗鼪](méi)有找到對(duì) Derived 類型的引用。

要向 XmlSerializer 聲明其他字段和屬性類型,您擁有多種選擇。您可以通過(guò) XmlInclude 屬性(由異常消息提示)聲明基類上的派生類型,如下所示:

[System.Xml.Serialization.XmlInclude( typeof( Derived ) )]
public class Base
{
    // ...
}

通過(guò)附加 XmlInclude 屬性,可以讓 XmlSerializer 在字段或?qū)傩员欢x為 Base 類型時(shí)序列化引用 Derived 類型對(duì)象的字段。

或者,您還可以僅在單個(gè)字段或?qū)傩陨下暶饔行ь愋?,而不是在基類上聲明派生類型。您可以?XmlElement、XmlAttribute 或 XmlArrayItem 屬性附加到字段,并且聲明該字段或?qū)傩钥梢砸玫念愋?。然后,XmlSerializer 的構(gòu)造函數(shù)會(huì)將序列化和反序列化這些類型所需的代碼添加到序列化類中。

讀取 StackTrace

InnerException 的 Message 屬性并不是唯一包含有價(jià)值信息的屬性。StackTrace 屬性傳達(dá)了更多有關(guān)錯(cuò)誤根源的詳細(xì)信息。在堆棧跟蹤的最頂端,您可以找到首先引發(fā)異常的方法的名稱。臨時(shí)程序集中的方法名稱對(duì)于序列化類遵循格式 Write_,對(duì)于反序列化類則遵循格式 Read_。在具有上述錯(cuò)誤命名空間的示例中,您可以看到異常源自名為 Read1_MyClass 的方法。稍后,我將向您說(shuō)明如何使用 Visual Studio 調(diào)試器設(shè)置斷點(diǎn)并單步執(zhí)行此方法。不過(guò),首先讓我們看一下圍繞反序列化 XML 文檔發(fā)生的常見(jiàn)問(wèn)題。

反序列化 XML 時(shí)發(fā)生的問(wèn)題

將 XML 文檔反序列化為對(duì)象圖不像將對(duì)象圖序列化為 XML 那樣容易出錯(cuò)。當(dāng)對(duì)象不十分匹配類型定義時(shí),XmlSerializer 會(huì)非常敏感,但如果反序列化的 XML 文檔不十分匹配對(duì)象,則它會(huì)非常寬容。對(duì)于與反序列化對(duì)象中的字段或?qū)傩圆粚?duì)應(yīng)的 XML 元素,XmlSerializer 不再引發(fā)異常,而只是簡(jiǎn)單地引發(fā)事件。如果您需要跟蹤反序列化的 XML 文檔與 XML 格式之間的匹配程度,則可以注冊(cè)這些事件的處理程序。然而,您不需要向 XmlSerializer 注冊(cè)事件處理程序以正確處理未映射的 XML 節(jié)點(diǎn)。

在反序列化過(guò)程中,只有幾種錯(cuò)誤條件會(huì)導(dǎo)致異常。最常見(jiàn)的條件有:

?

根元素的名稱或其命名空間不匹配期望的名稱。

?

枚舉數(shù)據(jù)類型呈現(xiàn)未定義的值。

?

文檔包含非法 XML。

就像序列化的情形一樣,每當(dāng)發(fā)生問(wèn)題時(shí),Deserialize() 方法都會(huì)引發(fā)帶有以下消息的 InvalidOperation 異常

There is an error in XML document (, ).

該異常通常在 InnerException 屬性中包含真正的異常。InnerException 的類型隨讀取 XML 文檔時(shí)發(fā)生的實(shí)際錯(cuò)誤而有所不同。如果序列化程序無(wú)法用傳遞給構(gòu)造函數(shù)的類型、通過(guò) XmlInclude 屬性指定的類型或者在傳遞給 XmlSerializer 構(gòu)造函數(shù)的某個(gè)更為復(fù)雜的重載的 Type[] 中指定的類型來(lái)匹配文檔的根元素,則 InnerException 為 InvalidCastException。請(qǐng)記住,XmlSerializer 將查看 Qname(即元素的名稱)和命名空間,以確定要將文檔反序列化為哪個(gè)類。它們都必須匹配 .NET 類中的聲明,以便 XmlSerializer 正確標(biāo)識(shí)與文檔的根元素相對(duì)應(yīng)的類型。

讓我們看一個(gè)示例:

[XmlRoot( Namespace="urn:my-namespace" )]
public class MyClass
{
  public string MyField;
}

反序列化以下 XML 文檔將導(dǎo)致異常,因?yàn)?MyClass 元素的 XML 命名空間并不像通過(guò) .NET 類上的 XmlRoot 屬性所聲明的那樣是 urn:my-namespace。

<MyClass> <MyField>Hello, World</MyField> </MyClass>

讓我們更進(jìn)一步地觀察一下該異常。異常 Message 比您從 Serialize() 方法中捕獲的消息更具描述性;至少它引用了文檔中導(dǎo)致 Deserialize() 失敗的位置。盡管如此,當(dāng)您處理大型 XML 文檔時(shí),查看文檔并確定錯(cuò)誤可能不會(huì)如此簡(jiǎn)單。InnerException 又一次提供了更好的信息。這一次,它顯示:

<MyClass xmlns=''> was not expected.

該消息仍然有一些模糊,但它的確向您指明了導(dǎo)致問(wèn)題的元素。您可以回頭仔細(xì)檢查一下 MyClass 類,并將元素名稱和 XML 命名空間與 .NET 類中的 XML 序列化屬性進(jìn)行比較。

反序列化無(wú)效的 XML

另一個(gè)經(jīng)常報(bào)告的問(wèn)題是無(wú)法反序列化無(wú)效的 XML 文檔。XML 規(guī)范禁止在 XML 文檔中使用某些控制字符。然而,有時(shí)您仍然會(huì)收到包含這些字符的 XML 文檔。正如您猜想的那樣,問(wèn)題暴露在 InvalidOperationException 中。盡管如此,在這種特殊情況下,InnerException 的類型是 XmlException。InnerException 的消息正中要害:

hexadecimal value <value>, is an invalid character

如果您通過(guò)將其 Normalization 屬性設(shè)置為 true 的 XmlTextReader 進(jìn)行反序列化,則可以避免此問(wèn)題。遺憾的是,ASP.NET Web 服務(wù)在內(nèi)部使用的 XmlTextReader 將其 Normalization 屬性設(shè)置為 false;也就是說(shuō),它將不會(huì)反序列化包含這些無(wú)效字符的 SOAP 消息。

來(lái)自構(gòu)造函數(shù)的異常

本文討論的最后一類問(wèn)題發(fā)生在 XmlSerializer 的構(gòu)造函數(shù)對(duì)傳入的類型進(jìn)行分析的時(shí)候。請(qǐng)記住,構(gòu)造函數(shù)將遞歸檢查類型層次結(jié)構(gòu)中的每個(gè)公共字段和屬性,以便創(chuàng)建用來(lái)處理序列化和反序列化的類。然后,它將即時(shí)編譯這些類,并加載得到的程序集。

在這一復(fù)雜的過(guò)程中,可能會(huì)發(fā)生許多不同的問(wèn)題:

?

根元素的聲明類型或者由屬性或字段引用的類型不提供默認(rèn)的構(gòu)造函數(shù)。

?

層次結(jié)構(gòu)中的某個(gè)類型實(shí)現(xiàn)了集合接口 Idictionary。

?

執(zhí)行對(duì)象圖中某個(gè)類型的構(gòu)造函數(shù)或?qū)傩栽L問(wèn)器時(shí),需要提升安全權(quán)限。

?

生成的序列化類的代碼無(wú)法編譯。

試圖向 XmlSerializer 構(gòu)造函數(shù)傳遞不可序列化的類型也會(huì)導(dǎo)致 InvalidOperationException,但這一次該異常不會(huì)包裝其他異常。Message 屬性包含對(duì)構(gòu)造函數(shù)拒絕傳入“類型”的原因的充分解釋。試圖序列化未實(shí)現(xiàn)不帶參數(shù)的構(gòu)造函數(shù)(默認(rèn)構(gòu)造函數(shù))的類的實(shí)例時(shí),將產(chǎn)生帶有以下 Message 的異常:

Test.NonSerializable cannot be serialized because it does not have a default public constructor.

另一方面,解決編譯錯(cuò)誤是非常復(fù)雜的。這些問(wèn)題暴露在帶有以下消息的 FileNotFoundException 中:

File or assembly name abcdef.dll, or one of its dependencies, was not found. File name: "abcdef.dll"
   at System.Reflection.Assembly.nLoad( ... )
   at System.Reflection.Assembly.InternalLoad( ... )
   at System.Reflection.Assembly.Load(...)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() 
    ....

您可能不知道“找不到文件”異常與實(shí)例化序列化程序?qū)ο笾g有什么關(guān)系,但請(qǐng)記?。簶?gòu)造函數(shù)寫(xiě)入 C# 文件并試圖編譯這些文件。該異常的調(diào)用堆棧提供了一些有用的信息,為這種懷疑提供了依據(jù)。當(dāng) XmlSerializer 試圖加載由調(diào)用 System.Reflection.Assembly.Load 方法的 CodeDOM 生成的程序集時(shí),發(fā)生了該異常。該異常沒(méi)有提供有關(guān) XmlSerializer 根據(jù)推測(cè)要?jiǎng)?chuàng)建的程序集不存在的原因的解釋。通常,該程序集不存在的原因是編譯失敗,這是由于序列化屬性生成了 C# 編譯器無(wú)法編譯的代碼,但這種情況很少出現(xiàn)。

當(dāng) XmlSerializer 運(yùn)行時(shí)所屬的帳戶或安全環(huán)境無(wú)法訪問(wèn) temp 目錄時(shí),也會(huì)發(fā)生該錯(cuò)誤。

XmlSerializer 所引發(fā)的任何異常錯(cuò)誤消息都不包含實(shí)際的編譯錯(cuò)誤,甚至連 InnerException 也不包含實(shí)際的編譯錯(cuò)誤。這使得解決這些異常變得非常困難,直到 Chris Sells 發(fā)布了他的 XmlSerializerPrecompiler 工具。

XmlSerializerPreCompiler

XmlSerializer PreCompiler 是一個(gè)命令行程序,它執(zhí)行與 XmlSerializer 的構(gòu)造函數(shù)相同的步驟。它可分析類型,生成序列化類,并編譯這些類 — 因?yàn)樗患兇庠O(shè)計(jì)為故障排除工具,所以它可以安全地向控制臺(tái)寫(xiě)入任何編譯錯(cuò)誤。

該工具使用起來(lái)非常方便。您只需使該工具指向包含導(dǎo)致異常的類型的程序集,并指定要預(yù)編譯的類型。讓我們看一個(gè)示例。當(dāng)您將 XmlElement 或 XmlArrayItem 屬性附加到定義為交錯(cuò)數(shù)組的字段時(shí),會(huì)發(fā)生一個(gè)經(jīng)常報(bào)告的問(wèn)題,如下面的示例所示:

namespace Test
{
  public class StringArray
  {
    [XmlElement( "arrayElement", typeof( string ) )]
    public string [][] strings;
  }
}

在為類型 Test.StringArray 實(shí)例化 XmlSerializer 對(duì)象時(shí),XmlSerializer 構(gòu)造函數(shù)會(huì)引發(fā) FileNotFoundException。如果您編譯該類并試圖序列化該類的實(shí)例,將得到 FileNotFoundException,但不會(huì)得到有關(guān)該問(wèn)題實(shí)質(zhì)的線索。XmlSerializerPreCompiler 可以為您提供缺少的信息。在我的示例中,StringArray 類被編譯為名為 XmlSer.exe 的程序集,并且我必須用下面的命令行運(yùn)行該工具:

XmlSerializerPreCompiler.exe XmlSer.exe Test.StringArray

第一個(gè)命令行參數(shù)指定了程序集,第二個(gè)參數(shù)定義了該程序集中要預(yù)編譯的類。該工具會(huì)向命令窗口寫(xiě)入大量信息。

stringarray

2. XmlSerializerPreCompiler 命令窗口輸出

需要查看的重要代碼行是具有編譯錯(cuò)誤的代碼行以及兩個(gè)與以下內(nèi)容類似的代碼行:

XmlSerializer-produced source:
C:\DOCUME~1\\LOCALS~1\Temp\.cs

現(xiàn)在,XmlSerializerPreCompiler 為我們提供了編譯錯(cuò)誤以及含有無(wú)法編譯的代碼的源文件的位置。

調(diào)試序列化代碼

通常情況下,XmlSerializer 會(huì)在不再需要序列化類的 C# 源文件時(shí)將其刪除。然而,有一個(gè)未經(jīng)證實(shí)的診斷開(kāi)關(guān),可用來(lái)指示 XmlSerializer 將這些文件保留在硬盤上。您可以在應(yīng)用程序的 .config 文件中設(shè)置此開(kāi)關(guān):

<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <switches> <add name="XmlSerialization.Compilation" value="4" /> </switches> </system.diagnostics> </configuration>

若此開(kāi)關(guān)出現(xiàn)在 .config 文件中,C# 源文件將保留在 temp 目錄中。如果您使用的計(jì)算機(jī)運(yùn)行 Windows 2000 或更高版本,則 temp 目錄的默認(rèn)位置是 \Documents and Settings\\LocalSettings\Temp 或 \Temp(對(duì)于在 ASP.NET 帳戶下運(yùn)行的 Web 應(yīng)用程序)。這些 C# 文件很容易丟失,因?yàn)樗鼈兊奈募雌饋?lái)非常奇怪并且是隨機(jī)生成的,例如:bdz6lq-t.0.cs。XmlSerializerPreCompiler 可設(shè)置該診斷開(kāi)關(guān),因此您可以在記事本或 Visual Studio 中打開(kāi)這些文件,以檢查 XmlSerializerPreCompiler 對(duì)其報(bào)告編譯錯(cuò)誤的代碼行。

您甚至可以逐句執(zhí)行這些臨時(shí)序列化類,因?yàn)樵\斷開(kāi)關(guān)還可以將含有調(diào)試符號(hào)的 .pdb 文件保留在硬盤上。如果您需要在序列化類中設(shè)置斷點(diǎn),則可以在 Visual Studio 調(diào)試器下運(yùn)行應(yīng)用程序。一旦您在輸出窗口中看到相關(guān)消息,表明應(yīng)用程序已經(jīng)從 temp 目錄中加載了具有這些奇特名稱的程序集,就可以打開(kāi)具有相應(yīng)名稱的 C# 文件,然后像在您自己的代碼中一樣設(shè)置斷點(diǎn)。

assemblyloaded

3. 來(lái)自診斷開(kāi)關(guān)的編譯錯(cuò)誤輸出

在序列化類中設(shè)置斷點(diǎn)之后,您需要執(zhí)行代碼以調(diào)用 XmlSerializer 對(duì)象上的 Serialize() 或 Deserialize() 方法。

您只能調(diào)試序列化和反序列化,而不能調(diào)試在構(gòu)造函數(shù)中運(yùn)行的代碼生成過(guò)程。

通過(guò)在序列化類中單步執(zhí)行,您能夠查明每個(gè)序列化問(wèn)題。如果您要單步執(zhí)行 SOAP 消息的反序列化,則可以使用上述技巧,這是因?yàn)?ASP.NET Web 服務(wù)和 Web 服務(wù)代理是在 XmlSerializer 之上構(gòu)建的。您需要做的只是將診斷開(kāi)關(guān)添加到您的 config 文件中,然后在反序列化消息的類中設(shè)置斷點(diǎn)。如果 WSDL 在生成代理類時(shí)沒(méi)有準(zhǔn)確地反映消息格式,則我偶爾會(huì)使用上述技巧來(lái)判斷正確的序列化屬性集。

小結(jié)

這些提示應(yīng)該可以幫助您診斷 XmlSerializer 中的序列化問(wèn)題。您遇到的大多數(shù)問(wèn)題都源自 XML 序列化屬性的錯(cuò)誤組合,或源自與要反序列化的類型不匹配的 XML。序列化屬性控制序列化類的代碼生成,并且可能導(dǎo)致編譯錯(cuò)誤或運(yùn)行時(shí)異常。通過(guò)仔細(xì)地檢查由 XmlSerializer 引發(fā)的異常,可幫助您識(shí)別運(yùn)行時(shí)異常的根源。如果您需要進(jìn)一步診斷問(wèn)題,則可以使用 XmlSerializerPreCompiler 工具來(lái)幫助您查找編譯錯(cuò)誤。如果任一種方法都不能幫助您找到問(wèn)題的根源,則可以檢查自動(dòng)創(chuàng)建的序列化類的代碼,并在調(diào)試器中逐句執(zhí)行這些代碼。

posted on 2006-04-12 12:34 夢(mèng)在天涯 閱讀(1785) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C#/.NET

公告

EMail:itech001#126.com

導(dǎo)航

統(tǒng)計(jì)

  • 隨筆 - 461
  • 文章 - 4
  • 評(píng)論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1812208
  • 排名 - 5

最新評(píng)論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              亚洲第一精品福利| 久久亚洲国产成人| 亚洲精品日本| 欧美精品在线观看91| 亚洲视频大全| 亚洲欧美精品在线观看| 国产亚洲欧洲997久久综合| 久久嫩草精品久久久精品| 亚洲午夜久久久久久久久电影院 | 一本色道久久综合狠狠躁篇的优点| 欧美香蕉视频| 欧美主播一区二区三区| 久久久久久黄| 一区二区激情| 欧美一区二区三区日韩视频| 亚洲国产精品一区二区尤物区| 亚洲毛片在线| 狠狠色噜噜狠狠色综合久| 亚洲黄色成人久久久| 国产精品视频精品| 欧美黄色影院| 国产精品日韩一区二区三区| 欧美成人首页| 国产精品一区二区久久| 亚洲成人在线免费| 亚洲私人影院在线观看| 国产精品少妇自拍| 欧美成人精品福利| 国产精品羞羞答答| 亚洲黄色成人久久久| 国产亚洲在线观看| 一区二区三区视频观看| 亚洲国产一区二区精品专区| 亚洲一区二区视频在线观看| 亚洲美女免费视频| 久久久精彩视频| 亚洲欧美日韩一区二区在线 | 久久久久久**毛片大全| 欧美精品色网| 欧美成人一区在线| 国产亚洲精品久久久| 99re66热这里只有精品4| 亚洲第一色在线| 欧美一级黄色录像| 亚洲欧美日韩综合aⅴ视频| 欧美成人嫩草网站| 欧美r片在线| 精久久久久久| 久久99伊人| 欧美在线免费一级片| 国产精品久久7| 日韩视频中文| 夜夜躁日日躁狠狠久久88av| 欧美刺激性大交免费视频| 老司机午夜精品视频| 国产一区二区三区日韩欧美| 亚洲欧美综合国产精品一区| 亚洲欧美国产高清| 欧美特黄一级| 在线午夜精品| 欧美一区二区观看视频| 国产精品夜夜嗨| 亚洲欧美日韩在线一区| 久久国产视频网| 国色天香一区二区| 久久精品国产99国产精品| 久久久久成人精品| 曰本成人黄色| 欧美成人官网二区| 99re66热这里只有精品3直播| 制服丝袜亚洲播放| 国产精品美女诱惑| 欧美一区二区国产| 美日韩精品视频免费看| 亚洲激情在线视频| 欧美图区在线视频| 欧美亚洲一区二区三区| 久热综合在线亚洲精品| 亚洲人www| 欧美视频在线观看视频极品| 亚洲一区二区欧美| 久久亚洲不卡| 99国产精品久久久| 国产精品欧美风情| 久久亚洲捆绑美女| 亚洲剧情一区二区| 久久精品男女| 99re66热这里只有精品4| 国产精品久久久久永久免费观看| 欧美一区二区三区在线观看| 国产精品一二三四| 亚洲毛片在线看| 久久久久综合网| 亚洲精品一区二区三区蜜桃久| 亚洲免费在线看| 一区二区在线视频观看| 欧美人与禽性xxxxx杂性| 亚洲女人天堂av| 亚洲国产成人精品久久久国产成人一区 | 亚洲精品乱码| 欧美一区免费视频| 亚洲欧洲日夜超级视频| 国产精品免费小视频| 免费不卡在线视频| 亚洲综合导航| 91久久精品日日躁夜夜躁国产| 亚洲欧美视频在线| 99re这里只有精品6| 国模套图日韩精品一区二区| 欧美另类视频| 久久久噜噜噜久久人人看| 一区二区三区国产精华| 亚洲高清不卡在线| 久久深夜福利免费观看| 亚洲一区免费视频| 亚洲精品资源美女情侣酒店| 一区二区在线视频播放| 国产女精品视频网站免费 | 欧美成年人视频网站| 欧美一区二区三区视频在线观看| 99精品视频一区| 亚洲国产精品久久久久秋霞影院| 久久精品官网| 午夜伦理片一区| 亚洲一区二区三区777| 亚洲激情啪啪| 亚洲电影免费在线| 精品动漫一区二区| 国语自产精品视频在线看8查询8 | 久久亚洲私人国产精品va| 性欧美大战久久久久久久久| 在线一区二区三区四区| 99re6这里只有精品| 亚洲精品午夜精品| 亚洲老板91色精品久久| 亚洲精品永久免费| 亚洲激情视频在线播放| 亚洲区中文字幕| 亚洲人成在线播放网站岛国| 亚洲激情图片小说视频| 亚洲第一狼人社区| 亚洲国产欧美在线人成| 亚洲欧洲一区二区在线播放| 亚洲经典三级| 一本大道久久a久久精二百| 艳妇臀荡乳欲伦亚洲一区| 99re6热在线精品视频播放速度| 亚洲毛片视频| 亚洲一区视频| 欧美在线视频免费| 久久久久久一区| 欧美成人蜜桃| 欧美视频在线观看免费| 国产欧美精品日韩| 韩日精品中文字幕| 亚洲激情社区| 亚洲一区二区av电影| 性欧美xxxx大乳国产app| 久久久不卡网国产精品一区| 麻豆精品传媒视频| 亚洲区一区二| 亚洲欧美一区二区三区久久 | 日韩一本二本av| 亚洲欧美日韩精品综合在线观看| 午夜激情亚洲| 亚洲麻豆国产自偷在线| 亚洲视频在线一区| 久久久视频精品| 亚洲第一久久影院| 在线综合+亚洲+欧美中文字幕| 欧美一区二区精品在线| 久久婷婷丁香| 国产精品久久一区二区三区| 一区二区三区在线看| 亚洲精品一区二区三区蜜桃久 | 亚洲直播在线一区| 久久亚洲一区| 夜夜嗨av一区二区三区四季av| 午夜在线一区| 欧美日韩国产一区二区三区| 国内外成人免费激情在线视频| 日韩视频在线观看国产| 欧美一区免费| 亚洲精品美女| 久久一区二区精品| 国产精品久久久999| 亚洲精品视频在线观看网站| 久久不射中文字幕| 日韩一本二本av| 嫩草成人www欧美| 国产一区二区三区四区三区四| 亚洲免费观看在线观看| 裸体歌舞表演一区二区 | 久久蜜桃资源一区二区老牛 | 午夜精品福利一区二区三区av| 欧美电影在线| 亚洲承认在线| 六月婷婷一区| 欧美在线综合| 国产农村妇女精品|