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

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

XmlSerializer 常見問題疑難解答

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


XmlSerializer 常見問題疑難解答

發布日期: 6/30/2004 | 更新日期: 6/30/2004

Christoph Schittko

適用于:
Microsoft ?Visual Studio ?.NET

摘要:Christoph Schittko 討論了各種相關技巧,以便診斷在使用 .NET 框架中的 XML 序列化技術將 XML 轉換為對象(以及反向轉換)時發生的常見問題。

*
本頁內容
簡介 簡介
XmlSerializer 的內部工作方式 XmlSerializer 的內部工作方式
序列化錯誤 序列化錯誤
聲明序列化類型 聲明序列化類型
反序列化 XML 時發生的問題 反序列化 XML 時發生的問題
來自構造函數的異常 來自構造函數的異常
小結 小結
致謝 致謝

簡介

.NET 框架中的 XmlSerializer 是一種很棒的工具,它將高度結構化的 XML 數據映射到 .NET 對象。XmlSerializer 在程序中通過單個 API 調用來執行 XML 文檔和對象之間的轉換。轉換的映射規則在 .NET 類中通過元數據屬性來表示。這一編程模型帶有自己的錯誤類別,開發人員需要了解如何診斷這些錯誤。例如,元數據屬性必須描述序列化程序可以處理的 XML 格式的所有變體。本文研究了在使用 XmlSerializer 構建基于 XML 的解決方案時可能發生的各種錯誤,并且討論了用來診斷這些錯誤的技巧和工具。

XmlSerializer 的內部工作方式

為了有效地解決在 XML 序列化過程中出現的問題,需要了解一下在非常簡單的 XmlSerializer 接口的內部發生了什么事情。與傳統的分析范型相反,.NET 框架中 System.Xml.Serialization 命名空間的 XmlSerializer 將 XML 文檔綁定到 .NET 類的實例。程序員不再需要編寫 DOM 或 SAX 分析代碼,而是通過直接在這些類中附加 .NET 元數據屬性來聲明性地設置綁定規則。因為所有分析規則都是通過屬性表示的,所以 XmlSerializer 的接口非常簡單。它主要由兩個方法組成:Serialize() 用于從對象實例生成 XML;Deserialize() 用于將 XML 文檔分析成對象圖。

在使用強類型的、能夠完美地映射到編程對象的結構嚴謹的 XML 格式時,這種方法非常有效。如果格式由 W3C架構定義,并且該架構由不帶混合型內容或且不過度使用通配符(xs:any 和 xs;anyAttribute)的 complexType 組成,則 XML 序列化是處理該數據的好方法。

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

為獲得 XmlSerializer 的高性能,需要付出雙重代價。首先是與給定 XmlSerializer 可以處理的 XML 格式有關的靈活性,其次是實例的構造需要進行大量的處理。

當您實例化 XmlSerializer 時,必須傳遞您試圖通過該序列化程序實例進行序列化和反序列化的對象的類型。序列化程序將檢查該類型的所有公共字段和屬性,以了解一個實例在運行時引用哪些類型。接下來,它將為一組類創建 C# 代碼,以便使用 System.CodeDOM 命名空間中的類處理序列化和反序列化。在此過程中,XmlSerializer 將檢查 XML 序列化屬性的反射類型,以便根據 XML 格式定義來自定義所創建的類。這些類隨后被編譯為臨時程序集,并由 Serialize() 和 Deserialize() 方法調用以執行 XML 到對象的轉換。

這個設置 XmlSerializer 的精巧過程和聲明性編程模型導致了三類錯誤,其中一些錯誤可能很難解決:

?

所生成的序列化類期望被序列化的對象完全符合元數據屬性所定義的類型結構。如果 XmlSerializer 遇到未聲明(顯式聲明或者是通過 XML 序列化屬性聲明)的類型,則對象將無法序列化。

?

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

?

最后,序列化類的創建及其隨后的編譯可能由于多種不同的原因而失敗。當傳遞給構造函數的類型或者由該類型引用的類型實現了不受支持的接口或者不能滿足 XmlSerializer 施加的限制時,類的創建可能會失敗。

當附加的屬性生成無法編譯的 C# 代碼時,編譯步驟可能會失敗。編譯步驟也可能由于與安全有關的原因而失敗。

下面各個部分將更深入地研究這些情況,并提供有關如何解決這些問題的指導和建議。

序列化錯誤

我們要研究的第一類錯誤發生在 Serialize() 方法中。當在運行時傳遞給該方法的對象圖中的類型與在設計時在類中聲明的類型不匹配時,將發生此類錯誤。您可以通過字段或屬性的類型定義來隱式聲明類型,也可以通過附加序列化屬性來顯式聲明類型。

typedecl

1. 對象圖中的類型聲明

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

例如,請看一下以下類層次結構:

public class Base
{
   public string Field;
}
public class Derived
{
  public string AnotherField;
}
public class Container
{
  public Base MyField;
}
如果您依賴繼承并且編寫了與下面類似的序列化代碼:
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!

您將得到發自 Serialize() 方法的異常,這是因為沒有 XmlSerializer 的顯式類型聲明。

發自 XmlSerializer 的異常

診斷這些問題的根源在開始時可能比較困難,這是因為來自 XmlSerializer 的異常看起來并沒有提供有關其產生原因的大量信息;至少,它們沒有在開發人員通常會查看的地點提供信息。

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

There was an error generating the XML document.

該消息最多也就是令人討厭的,因為當您看到 XmlSerializer 引發異常時,就已經猜到了這一點。現在,您只好無奈地發現該異常的 Message 無法幫助您解決問題。

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

讀取異常消息

得到“實際”的異常信息的竅門是檢查該異常的 InnerException 屬性。InnerException 引用了從序列化類內部引發的實際異常。它包含有關該問題及其發生地點的非常詳細的信息。您在運行上述示例時捕獲的異常將包含帶有以下消息的 InnerException:

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

您可以通過直接檢查 InnerException 或者通過調用該異常的 ToString() 方法來得到此消息。下面的代碼片段演示了一個異常處理程序,它寫出了在反序列化對象的過程中發生的所有異常中的信息:

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 );            
}

聲明序列化類型

要解決上述示例中的問題,您只需讀取 InnerException 的消息并實現建議的解決方案。傳遞給 Serialize 方法的對象圖中的一個字段引用了一個類型為 Derived 的對象,但并未將該字段聲明為序列化 Derived 類型的對象。盡管該對象圖在 .NET 類型系統中完全合法,但 XmlSerializer 的構造函數在遍歷容器類型的字段時,并不知道為 Derived 類型的對象創建了序列化代碼,這是因為它沒有找到對 Derived 類型的引用。

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

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

通過附加 XmlInclude 屬性,可以讓 XmlSerializer 在字段或屬性被定義為 Base 類型時序列化引用 Derived 類型對象的字段。

或者,您還可以僅在單個字段或屬性上聲明有效類型,而不是在基類上聲明派生類型。您可以將 XmlElement、XmlAttribute 或 XmlArrayItem 屬性附加到字段,并且聲明該字段或屬性可以引用的類型。然后,XmlSerializer 的構造函數會將序列化和反序列化這些類型所需的代碼添加到序列化類中。

讀取 StackTrace

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

反序列化 XML 時發生的問題

將 XML 文檔反序列化為對象圖不像將對象圖序列化為 XML 那樣容易出錯。當對象不十分匹配類型定義時,XmlSerializer 會非常敏感,但如果反序列化的 XML 文檔不十分匹配對象,則它會非常寬容。對于與反序列化對象中的字段或屬性不對應的 XML 元素,XmlSerializer 不再引發異常,而只是簡單地引發事件。如果您需要跟蹤反序列化的 XML 文檔與 XML 格式之間的匹配程度,則可以注冊這些事件的處理程序。然而,您不需要向 XmlSerializer 注冊事件處理程序以正確處理未映射的 XML 節點。

在反序列化過程中,只有幾種錯誤條件會導致異常。最常見的條件有:

?

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

?

枚舉數據類型呈現未定義的值。

?

文檔包含非法 XML。

就像序列化的情形一樣,每當發生問題時,Deserialize() 方法都會引發帶有以下消息的 InvalidOperation 異常

There is an error in XML document (, ).

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

讓我們看一個示例:

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

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

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

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

<MyClass xmlns=''> was not expected.

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

反序列化無效的 XML

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

hexadecimal value <value>, is an invalid character

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

來自構造函數的異常

本文討論的最后一類問題發生在 XmlSerializer 的構造函數對傳入的類型進行分析的時候。請記住,構造函數將遞歸檢查類型層次結構中的每個公共字段和屬性,以便創建用來處理序列化和反序列化的類。然后,它將即時編譯這些類,并加載得到的程序集。

在這一復雜的過程中,可能會發生許多不同的問題:

?

根元素的聲明類型或者由屬性或字段引用的類型不提供默認的構造函數。

?

層次結構中的某個類型實現了集合接口 Idictionary

?

執行對象圖中某個類型的構造函數或屬性訪問器時,需要提升安全權限。

?

生成的序列化類的代碼無法編譯。

試圖向 XmlSerializer 構造函數傳遞不可序列化的類型也會導致 InvalidOperationException,但這一次該異常不會包裝其他異常。Message 屬性包含對構造函數拒絕傳入“類型”的原因的充分解釋。試圖序列化未實現不帶參數的構造函數(默認構造函數)的類的實例時,將產生帶有以下 Message 的異常:

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

另一方面,解決編譯錯誤是非常復雜的。這些問題暴露在帶有以下消息的 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() 
    ....

您可能不知道“找不到文件”異常與實例化序列化程序對象之間有什么關系,但請記住:構造函數寫入 C# 文件并試圖編譯這些文件。該異常的調用堆棧提供了一些有用的信息,為這種懷疑提供了依據。當 XmlSerializer 試圖加載由調用 System.Reflection.Assembly.Load 方法的 CodeDOM 生成的程序集時,發生了該異常。該異常沒有提供有關 XmlSerializer 根據推測要創建的程序集不存在的原因的解釋。通常,該程序集不存在的原因是編譯失敗,這是由于序列化屬性生成了 C# 編譯器無法編譯的代碼,但這種情況很少出現。

當 XmlSerializer 運行時所屬的帳戶或安全環境無法訪問 temp 目錄時,也會發生該錯誤。

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

XmlSerializerPreCompiler

XmlSerializer PreCompiler 是一個命令行程序,它執行與 XmlSerializer 的構造函數相同的步驟。它可分析類型,生成序列化類,并編譯這些類 — 因為它被純粹設計為故障排除工具,所以它可以安全地向控制臺寫入任何編譯錯誤。

該工具使用起來非常方便。您只需使該工具指向包含導致異常的類型的程序集,并指定要預編譯的類型。讓我們看一個示例。當您將 XmlElement 或 XmlArrayItem 屬性附加到定義為交錯數組的字段時,會發生一個經常報告的問題,如下面的示例所示:

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

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

XmlSerializerPreCompiler.exe XmlSer.exe Test.StringArray

第一個命令行參數指定了程序集,第二個參數定義了該程序集中要預編譯的類。該工具會向命令窗口寫入大量信息。

stringarray

2. XmlSerializerPreCompiler 命令窗口輸出

需要查看的重要代碼行是具有編譯錯誤的代碼行以及兩個與以下內容類似的代碼行:

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

現在,XmlSerializerPreCompiler 為我們提供了編譯錯誤以及含有無法編譯的代碼的源文件的位置。

調試序列化代碼

通常情況下,XmlSerializer 會在不再需要序列化類的 C# 源文件時將其刪除。然而,有一個未經證實的診斷開關,可用來指示 XmlSerializer 將這些文件保留在硬盤上。您可以在應用程序的 .config 文件中設置此開關:

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

若此開關出現在 .config 文件中,C# 源文件將保留在 temp 目錄中。如果您使用的計算機運行 Windows 2000 或更高版本,則 temp 目錄的默認位置是 \Documents and Settings\\LocalSettings\Temp 或 \Temp(對于在 ASP.NET 帳戶下運行的 Web 應用程序)。這些 C# 文件很容易丟失,因為它們的文件名看起來非常奇怪并且是隨機生成的,例如:bdz6lq-t.0.cs。XmlSerializerPreCompiler 可設置該診斷開關,因此您可以在記事本或 Visual Studio 中打開這些文件,以檢查 XmlSerializerPreCompiler 對其報告編譯錯誤的代碼行。

您甚至可以逐句執行這些臨時序列化類,因為診斷開關還可以將含有調試符號的 .pdb 文件保留在硬盤上。如果您需要在序列化類中設置斷點,則可以在 Visual Studio 調試器下運行應用程序。一旦您在輸出窗口中看到相關消息,表明應用程序已經從 temp 目錄中加載了具有這些奇特名稱的程序集,就可以打開具有相應名稱的 C# 文件,然后像在您自己的代碼中一樣設置斷點。

assemblyloaded

3. 來自診斷開關的編譯錯誤輸出

在序列化類中設置斷點之后,您需要執行代碼以調用 XmlSerializer 對象上的 Serialize() 或 Deserialize() 方法。

您只能調試序列化和反序列化,而不能調試在構造函數中運行的代碼生成過程。

通過在序列化類中單步執行,您能夠查明每個序列化問題。如果您要單步執行 SOAP 消息的反序列化,則可以使用上述技巧,這是因為 ASP.NET Web 服務和 Web 服務代理是在 XmlSerializer 之上構建的。您需要做的只是將診斷開關添加到您的 config 文件中,然后在反序列化消息的類中設置斷點。如果 WSDL 在生成代理類時沒有準確地反映消息格式,則我偶爾會使用上述技巧來判斷正確的序列化屬性集。

小結

這些提示應該可以幫助您診斷 XmlSerializer 中的序列化問題。您遇到的大多數問題都源自 XML 序列化屬性的錯誤組合,或源自與要反序列化的類型不匹配的 XML。序列化屬性控制序列化類的代碼生成,并且可能導致編譯錯誤或運行時異常。通過仔細地檢查由 XmlSerializer 引發的異常,可幫助您識別運行時異常的根源。如果您需要進一步診斷問題,則可以使用 XmlSerializerPreCompiler 工具來幫助您查找編譯錯誤。如果任一種方法都不能幫助您找到問題的根源,則可以檢查自動創建的序列化類的代碼,并在調試器中逐句執行這些代碼。

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

公告

EMail:itech001#126.com

導航

統計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1816192
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              亚洲精品一区二区三| 在线亚洲观看| 老司机67194精品线观看| 亚洲天堂av在线免费| 国产美女精品人人做人人爽| 欧美在线播放视频| 欧美一区二区三区免费在线看| 亚洲盗摄视频| 欧美成人免费网站| 在线午夜精品自拍| 亚洲欧美精品在线| 国内欧美视频一区二区| 免费毛片一区二区三区久久久| 久久只有精品| 一区二区三区高清视频在线观看| 中文亚洲免费| 国产一区在线视频| 亚洲黄色av| 国产精品日本| 欧美电影在线免费观看网站| 欧美日韩精品中文字幕| 欧美一区二区三区婷婷月色 | 久久一日本道色综合久久| 久久久久亚洲综合| 在线午夜精品自拍| 久久xxxx| 亚洲午夜激情网页| 久久精品国产免费| 一区二区日韩伦理片| 欧美一区二区三区啪啪| 99精品欧美| 久久精品亚洲热| 亚洲在线观看| 牛牛影视久久网| 久久久国产一区二区三区| 欧美国产综合| 久久婷婷国产麻豆91天堂| 欧美日韩免费观看一区=区三区| 欧美在线影院| 欧美日韩在线观看视频| 欧美成人午夜免费视在线看片| 国产精品久久久久久一区二区三区| 久久影视精品| 国产精品一区二区在线| 亚洲人体1000| 亚洲啪啪91| 久久久999精品免费| 性欧美1819性猛交| 欧美视频免费在线| 亚洲国产小视频在线观看| 伊人成人在线视频| 午夜精品在线| 欧美一进一出视频| 国产精品久久国产三级国电话系列| 亚洲国产日韩欧美| 亚洲国产天堂久久综合网| 久久精品国产免费观看| 久久国产66| 国模叶桐国产精品一区| 午夜在线不卡| 久久精品伊人| 国产亚洲激情在线| 欧美一级淫片播放口| 香蕉久久国产| 国产日韩欧美| 香港成人在线视频| 久久精品二区| 黑人巨大精品欧美黑白配亚洲 | 狂野欧美一区| 国产在线拍揄自揄视频不卡99| 亚洲欧美激情一区二区| 欧美亚洲视频一区二区| 国产精品久久久| 亚洲天堂av在线免费| 性视频1819p久久| 国产欧美日韩另类视频免费观看| 亚洲一区二区三区四区视频| 性欧美1819sex性高清| 国产日韩欧美三级| 久久国产高清| 亚洲电影免费观看高清完整版在线| 亚洲国产精品成人综合色在线婷婷| 久久手机免费观看| 亚洲国产高清视频| 一区二区三区久久精品| 国产精品久久国产精品99gif | 欧美中在线观看| 国产日韩欧美一区在线 | 亚洲香蕉网站| 欧美一区二视频在线免费观看| 国产午夜精品一区二区三区视频| 欧美中文字幕在线播放| 欧美国产乱视频| 亚洲天堂黄色| 国语自产精品视频在线看抢先版结局| 久久久久一本一区二区青青蜜月| 亚洲激情午夜| 亚洲欧美日韩一区二区| 在线播放亚洲| 欧美视频日韩| 久久国产天堂福利天堂| 欧美激情中文不卡| 亚洲自拍高清| 136国产福利精品导航| 欧美日韩在线播| 久久九九电影| 在线一区二区三区做爰视频网站| 久久婷婷久久| 中文日韩电影网站| 伊人成人在线| 国产精品嫩草99av在线| 久久综合一区二区三区| 亚洲网址在线| 亚洲国产精彩中文乱码av在线播放| 亚洲欧美成人一区二区三区| 在线成人亚洲| 国产欧美日韩亚洲一区二区三区| 欧美成人免费在线视频| 欧美一级久久久| 一区二区三区精品在线| 欧美激情第六页| 久久久久久9999| 午夜精品免费在线| 亚洲精品综合精品自拍| 加勒比av一区二区| 国产日本欧美一区二区三区| 欧美日韩一区免费| 欧美mv日韩mv亚洲| 久久久久国产一区二区| 亚洲欧美日韩直播| 在线亚洲美日韩| 亚洲精选大片| 亚洲国产另类久久久精品极度| 久久免费精品日本久久中文字幕| 午夜精品国产| 亚洲免费一级电影| 一区二区三区蜜桃网| 亚洲精品在线视频| 91久久线看在观草草青青| 激情综合色综合久久| 国产午夜精品久久| 国产精品网站在线播放| 国产精品成人v| 欧美性大战久久久久久久| 欧美精品一区二| 欧美日韩蜜桃| 欧美三日本三级少妇三2023| 欧美日韩国产精品自在自线| 欧美bbbxxxxx| 欧美高清视频免费观看| 欧美久久久久中文字幕| 欧美成人精品h版在线观看| 久久男人av资源网站| 久久综合激情| 欧美精品在线观看91| 欧美日韩精品不卡| 欧美午夜精品一区| 国产精品综合视频| 国产欧美精品久久| 黑人一区二区| 亚洲大胆女人| av不卡在线观看| 亚洲女人天堂av| 久久国产精品72免费观看| 久久久久久黄| 欧美国产日韩在线| 亚洲美洲欧洲综合国产一区| 这里只有精品视频在线| 欧美一区成人| 久久综合色播五月| 欧美日韩国产色视频| 国产精品视频九色porn| 国内成人精品视频| 亚洲国产合集| 亚洲在线视频网站| 久久视频在线看| 91久久久久| 午夜精品视频在线观看| 女女同性精品视频| 国产精品入口夜色视频大尺度| 国产亚洲精品aa午夜观看| 最新日韩在线| 欧美一区二区三区免费看| 免费观看在线综合| 一本一本大道香蕉久在线精品| 欧美在线观看网址综合| 欧美激情一区二区三区全黄| 国产欧美日韩综合| 日韩午夜三级在线| 麻豆精品精华液| 亚洲午夜在线| 欧美成人精品一区二区| 国产三级精品在线不卡| 亚洲精品你懂的| 久久亚洲国产精品日日av夜夜| 亚洲理论电影网| 毛片一区二区三区| 国产日韩欧美亚洲一区| 一本色道88久久加勒比精品| 久久久欧美精品sm网站|