<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      通過實(shí)例模擬ASP.NET MVC的Model綁定機(jī)制:簡單類型+復(fù)雜類型

      總的來說,針對目標(biāo)Action方法參數(shù)的Model綁定完全由組件ModelBinder來實(shí)現(xiàn),在默認(rèn)情況下使用的ModelBinder類型為DefaultModelBinder,接下來我們將按照逐層深入的方式介紹實(shí)現(xiàn)在DefaultModelBinder的默認(rèn)Model綁定機(jī)制。[源代碼從這里下載][本文已經(jīng)同步到《How ASP.NET MVC Works?》中]

      目錄
      一、簡單類型
      二、復(fù)雜類型
      三、數(shù)組
      四、集合
      五、字典

      一、簡單類型

      對于旨在綁定目標(biāo)Action方法參數(shù)值的Model來說,最簡單的莫過于簡單參數(shù)類型的情況。通過《初識Model元數(shù)據(jù)》的介紹我們知道,復(fù)雜類型和簡單類型之間的區(qū)別僅僅在于是否支持針對字符串類型的轉(zhuǎn)換。由于參數(shù)值的數(shù)據(jù)源在請求中以字符串的形式存在,對于支持字符串轉(zhuǎn)換的簡單類型來說,可以直接通過類型轉(zhuǎn)換得到參數(shù)值。我們通過一個簡單的實(shí)例來模擬實(shí)現(xiàn)在DefaultModelBinder中針對簡單類型的Model綁定。如下所示的是我們自定義的DefaultModelBinder,其屬性ValueProvider用于從請求中提供相應(yīng)的數(shù)據(jù)值,該屬性在構(gòu)造函數(shù)中被初始化。

         1: public class DefaultModelBinder
         2: {
         3:     public IValueProvider ValueProvider { get; private set; }
         4:     public DefaultModelBinder(IValueProvider valueProvider)
         5:     {
         6:         this.ValueProvider = valueProvider;
         7:     }
         8:  
         9:      public IEnumerable<object> GetParameterValues(ActionDescriptor actionDescriptor)
        10:     {
        11:         foreach (ParameterDescriptor parameterDescriptor in actionDescriptor.GetParameters())
        12:         {
        13:             string prefix = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
        14:             yield return GetParameterValue(parameterDescriptor, prefix);
        15:         }
        16:     }
        17:  
        18:     public object GetParameterValue(ParameterDescriptor parameterDescriptor, string prefix)
        19:     {
        20:         object parameterValue = BindModel(parameterDescriptor.ParameterType, prefix);
        21:         if (null == parameterValue && string.IsNullOrEmpty(parameterDescriptor.BindingInfo.Prefix))
        22:         {
        23:             parameterValue = BindModel( parameterDescriptor.ParameterType, "");
        24:         }
        25:         return parameterValue ?? parameterDescriptor.DefaultValue;
        26:      }
        27:  
        28:     public object BindModel(Type parameterType, string prefix)
        29:     {
        30:         if (!this.ValueProvider.ContainsPrefix(prefix))
        31:         {
        32:             return null;
        33:         }
        34:         return this.ValueProvider.GetValue(prefix).ConvertTo(parameterType);
        35:     }
        36: }

      方法GetParameterValues根據(jù)指定的用于描述Action方法的ActionDescriptor獲取最終執(zhí)行該方法的所有參數(shù)值。在該方法中,我們通過調(diào)用ActionDescriptor的GetParameters方法得到用于描述其參數(shù)的所有ParameterDescriptor對象,并將每一個ParameterDescriptor作為參數(shù)調(diào)用GetParameterValue方法得到具體某個參數(shù)的值。GetParameterValue除了接受一個類型為ParameterDescriptor的參數(shù)外,還接受一個用于表示前綴的字符串參數(shù)。如果通過ParameterDescriptor的BindingInfo屬性表示的ParameterBindingInfo對象具有前綴,則采用該前綴;否則采用參數(shù)名稱作為前綴。

      對于GetParameterValue方法來說,它又通過調(diào)用另一個將參數(shù)類型作為參數(shù)的BindModel方法來提供具體的參數(shù)值,BindModel方法同樣接受一個表示前綴的字符串作為其第二個參數(shù)。GetParameterValue最初將通過ParameterDescriptor獲取到的參數(shù)值和前綴作為參數(shù)調(diào)用BindModel方法,如果返回值為Null并且參數(shù)并沒有顯示執(zhí)行前綴,會傳入一個空字符串作為前綴再一次調(diào)用BindModel方法,這實(shí)際上模擬了之前提到過的去除前綴的后備Model綁定機(jī)制(針對于ModelBindingContext的FallbackToEmptyPrefix屬性)。如果最終得到的對象不為Null,則將其作為參數(shù)值返回;否則返回參數(shù)的默認(rèn)值。

      BindModel方法的邏輯非常簡單。先將傳入的前綴作為參數(shù)調(diào)用ValueProvider的ContainsPrefix方法判斷當(dāng)前的ValueProvider保持的數(shù)據(jù)是否具有該前綴。如果返回之為False,直接返回Null,否則以此前綴作為Key調(diào)用GetValue方法得到一個ValueProviderResult調(diào)用,并最終調(diào)用ConvertTo方法轉(zhuǎn)換為參數(shù)類型并返回。

      為了驗(yàn)證我們自定義的DefaultModelBinder能夠真正地用于針對簡單參數(shù)類型的Model綁定沒我們將它應(yīng)用到一個具體的ASP.NET MVC應(yīng)用中。在通過Visual Studio的ASP.NET MVC項(xiàng)目模板創(chuàng)建的空Web應(yīng)用中,我們創(chuàng)建了如下一個默認(rèn)的HomeController。HomeController具有一個ModelBinder屬性,其類型正是我們自定義的DefaultModelBinder,該屬性通過方法GetValueProvider提供。

         1: public class HomeController : Controller
         2: {
         3:     public DefaultModelBinder ModelBinder { get; private set; }
         4:     public HomeController()
         5:     {
         6:         this.ModelBinder = new DefaultModelBinder(GetValueProvider());
         7:     }       
         8:     private void InvokeAction(string actionName)
         9:     {
        10:         ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(typeof(HomeController));
        11:         ReflectedActionDescriptor actionDescriptor = (ReflectedActionDescriptor)controllerDescriptor
        12:             .FindAction(ControllerContext, actionName);
        13:         actionDescriptor.MethodInfo.Invoke(this,this.ModelBinder.GetParameterValues(actionDescriptor).ToArray());
        14:     }
        15:     public void Index()
        16:     {
        17:         InvokeAction("Action");
        18:     }
        19:  
        20:     private IValueProvider GetValueProvider()
        21:     {
        22:         NameValueCollection requestData = new NameValueCollection();
        23:         requestData.Add("foo", "abc");
        24:         requestData.Add("bar", "123");
        25:         requestData.Add("baz", "123.45");
        26:         return new NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);
        27:     }
        28:     public void Action(string foo, [Bind(Prefix="baz")]double bar)
        29:     {
        30:         Response.Write(string.Format("{0}: {1}<br/>", "foo", foo));
        31:         Response.Write(string.Format("{0}: {1}<br/>", "bar", bar));
        32:     }
        33: }

      InvokeAction方法用于執(zhí)行指定的Action方法。在該方法中我們先根據(jù)當(dāng)前Controller的類型創(chuàng)建一個ControllerDescriptor對象,并通過調(diào)其FindAction方法得到用于描述指定Action方法的ActionDescriptor對象。通過之前的介紹我們知道這是一個ReflectedActionDescriptor對象,所以我們將其轉(zhuǎn)化成ReflectedActionDescriptor類型得到Action方法對應(yīng)的MethodInfo對象。最后調(diào)用DefaultModelBinder的GetParameterValues方法得到目標(biāo)Action方法所有的參數(shù),將其傳入MethodInfo的Invoke方法以反射的形式對指定的Action方法進(jìn)行執(zhí)行。

      默認(rèn)的Action方法Index中我們通過執(zhí)行InvokeAction方法來執(zhí)行定義在HomeController的Action方法。通過上面的代碼片斷可以看出,該方法的兩個參數(shù)foo和bar均為簡單類型(string和double),在參數(shù)bar上還應(yīng)用了BindAttribute并指定了相應(yīng)的前綴(“baz”)。在該Action方法中,我們將兩個參數(shù)值呈現(xiàn)出來。

      而在用于提供ValueProvider的GetValueProvider方法返回的是一個NameValueCollectionValueProvider對象。作為數(shù)據(jù)源的NameValueCollection對象包含三個名稱為foo、bar和baz的數(shù)據(jù)(abc、123、123.45),我們可以將它們看成是Post的標(biāo)單輸入元素。

      當(dāng)我們運(yùn)行該程序的時候會在瀏覽器中得到如下的輸出結(jié)果。我們可以看到目標(biāo)Action方法的兩個參數(shù)值均通過我們自定義的DefaultModelBinder得到了有效的綁定。而實(shí)際上參數(shù)值的提供最終是通過ValueProvider實(shí)現(xiàn)的,它在默認(rèn)的情況下會根據(jù)參數(shù)名稱進(jìn)行匹配(foo參數(shù)),如果參數(shù)應(yīng)用BindAttribute并顯式指定了前綴,則會按照這個前綴進(jìn)行匹配(bar參數(shù))。

         1: foo: abc
         2: bar: 123.45

      二、復(fù)雜類型

      對于簡單類型的參數(shù)來說,由于支持與字符串類型之間的轉(zhuǎn)換,相應(yīng)ValueProvider可以直接從數(shù)據(jù)源中提取相應(yīng)的數(shù)據(jù)并直接轉(zhuǎn)換成參數(shù)類型。所以針對簡單類型的Model綁定是一步到位的過程,但是針對復(fù)雜類型的Model綁定就沒有這么簡單了。復(fù)雜對象可以表示為一個樹形層次化結(jié)構(gòu),其對象本身和屬性代表相應(yīng)的節(jié)點(diǎn),葉子節(jié)點(diǎn)代表簡單數(shù)據(jù)類型屬性。而ValueProvider采用的數(shù)據(jù)源是一個扁平的數(shù)據(jù)結(jié)構(gòu),它通過基于屬性名稱前綴的Key實(shí)現(xiàn)與這個對象樹中對應(yīng)葉子節(jié)點(diǎn)的映射。

         1: public class Contact
         2: {
         3:     public string Name { get; set; }
         4:     public string PhoneNo { get; set; }
         5:     public string EmailAddress { get; set; }
         6:     public Address Address { get; set; }
         7: }
         8: public class Address
         9: {
        10:     public string Province { get; set; }
        11:     public string City { get; set; }
        12:     public string District { get; set; }
        13:     public string Street { get; set; }
        14: }

      以上面定于得這個Contact類型為例,它具有三個簡單類型的屬性(Name、PhoneNo和EmailAddress)和復(fù)雜類型Address的屬性;而Address屬性具有四個簡單類型的屬性。一個Contact對象的數(shù)據(jù)結(jié)構(gòu)可以通過如下圖所示的樹來表示,這個樹種的所有葉子節(jié)點(diǎn)均為簡單類型。如果我們需要通過一個ValueProvider來構(gòu)建一個完整的Contact對象,它必須能夠提供所有所有葉子節(jié)點(diǎn)的數(shù)值,而ValueProvider通過基于屬性名稱前綴的Key實(shí)現(xiàn)與對應(yīng)的葉子節(jié)點(diǎn)的映射。

      image

      實(shí)際上當(dāng)我們調(diào)用HtmlHelper<TModel>的模板方法EditorFor/EditorForModel的時候就是按照這樣的匹配方式對標(biāo)單元素進(jìn)行命名的。假設(shè)在將Contact作為Model類型的強(qiáng)類型View中,我們通過調(diào)用HtmlHelper<TModel>的擴(kuò)展方法EditorFor將Model對象的所有信息以編輯的模式呈現(xiàn)出來。

         1: @model Contact
         2: @Html.EditorFor(m => m.Name)
         3: @Html.EditorFor(m => m.PhoneNo)
         4: @Html.EditorFor(m => m.EmailAddress)
         5: @Html.EditorFor(m => m.Address.Province)
         6: @Html.EditorFor(m => m.Address.City)
         7: @Html.EditorFor(m => m.Address.District)
         8: @Html.EditorFor(m => m.Address.Street)

      下面的代碼片斷代表了作為Model對象的Contact在最終呈現(xiàn)出來的View中代表的HTML,我們可以清楚地看到這些<input>表單元素完全是根據(jù)屬性名稱和類型層次結(jié)構(gòu)進(jìn)行命名的。隨便提一下,對于基于提交表單的Model綁定來說,作為匹配的是表單元素的name屬性而非id屬性,所以這里的命名指的是name屬性而非id屬性。

         1: <input id="Name" name="Name" type="text" ... />
         2: <input id="PhoneNo" name="PhoneNo" type="text" ... />
         3: <input id="EmailAddress" name="EmailAddress" type="text" ... />
         4: <input id="Address_Province" name="Address.Province" type="text" ... />
         5: <input id="Address_City" name="Address.City" type="text" ... />
         6: <input id="Address_District" name="Address.District" type="text" ... />
         7: <input id="Address_Street" name="Address.Street" type="text"... />

      對于用于模擬默認(rèn)Model綁定機(jī)制的自定義DefaultModelBinder來說,我們僅僅提供了針對簡單類型的綁定,現(xiàn)在我們對其進(jìn)行完善是之可以提供對復(fù)雜類型的Model綁定。如下面的代碼片斷所示,在BindModel方法中我們創(chuàng)建了一個基于參數(shù)類型的ModelMetadata對象,并根據(jù)其IsComplexType屬性判斷參數(shù)類型是否為復(fù)雜類型。

         1: public class DefaultModelBinder
         2: {
         3:     //其他成員
         4:     public object BindModel(Type parameterType, string prefix)
         5:     {
         6:         if (!this.ValueProvider.ContainsPrefix(prefix))
         7:         {
         8:             return null;
         9:         }
        10:         ModelMetadata modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, parameterType);
        11:         if (!modelMetadata.IsComplexType)
        12:         {
        13:             return this.ValueProvider.GetValue(prefix).ConvertTo(parameterType);
        14:         }            
        15:         object model = CreateModel(parameterType);
        16:         foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(parameterType))
        17:         {                
        18:             string key = string.IsNullOrEmpty(prefix) ? property.Name : prefix + "." + property.Name;
        19:             property.SetValue(model, BindModel(property.PropertyType, key));
        20:         }
        21:         return model;
        22:     }
        23:     private object CreateModel(Type modelType)
        24:     {
        25:         Type type = modelType;
        26:         if (modelType.IsGenericType)
        27:         {
        28:             Type genericTypeDefinition = modelType.GetGenericTypeDefinition();
        29:             if (genericTypeDefinition == typeof(IDictionary<,>))
        30:             {
        31:                 type = typeof(Dictionary<,>).MakeGenericType(modelType.GetGenericArguments());
        32:             }
        33:             else if (((genericTypeDefinition == typeof(IEnumerable<>)) || (genericTypeDefinition == typeof(ICollection<>))) ||(genericTypeDefinition == typeof(IList<>)))
        34:             {
        35:                 type = typeof(List<>).MakeGenericType(
        36:                 modelType.GetGenericArguments());
        37:             }
        38:         }
        39:         return Activator.CreateInstance(type);
        40:     }
        41: }

      如果參數(shù)為復(fù)雜類型,則通過調(diào)用CreateModel方法以反射的方式創(chuàng)建Model對象。CreateModel方法會被用于后面我們會介紹的基于集合和字典的Model綁定,所以我們這里還針對泛型的IDictionary<,>、IEnumerable<>、ICollection<>和IList<>類型作了相應(yīng)地處理。具體來說,如果參數(shù)類型為IDictionary<,>,則創(chuàng)建一個Dictionary<,>對象,而對后三者則創(chuàng)建一個List<>對象,具體的泛型參數(shù)根據(jù)參數(shù)類型獲取。對于一般的類型,我們直接通過Activator的CreateInstance方法根據(jù)參數(shù)類型創(chuàng)建相應(yīng)的Model對象。

      通過CreateModel方法創(chuàng)建的是針對參數(shù)類型的“空”對象,我們需要通過Model綁定對它的相關(guān)屬性進(jìn)行初始化。在BindModel方法中,我們遍歷參數(shù)類型的所有屬性,并在現(xiàn)有前綴的基礎(chǔ)上加上“.{屬性名稱}”(如果當(dāng)前前綴為空,則直接采用屬性名稱)作為綁定對應(yīng)屬性的前綴遞歸地調(diào)用BindModel方法得到屬性值。我們最終通過反射的方式將得到值對屬性進(jìn)行賦值。

      現(xiàn)在我們采用我們完善后的DefaultModelBinder來進(jìn)行針對復(fù)雜類型的Model綁定。如下面的代碼片斷所示,我們對HomeController的Action方法進(jìn)行了相應(yīng)的修改使之具有兩個Contact類型的參數(shù)foo和bar。在Action方法中,我們將這兩個參數(shù)代表的Contact對象的相關(guān)信息呈現(xiàn)出來。

         1: public class HomeController : Controller
         2: {
         3:     public DefaultModelBinder ModelBinder { get; private set; }
         4:     public HomeController()
         5:     {
         6:         this.ModelBinder = new DefaultModelBinder(GetValueProvider());
         7:     }
         8:  
         9:     private IValueProvider GetValueProvider()
        10:     {
        11:         NameValueCollection requestData = new NameValueCollection();
        12:         requestData.Add("Name", "張三");
        13:         requestData.Add("PhoneNo", "123456789");
        14:         requestData.Add("EmailAddress", "zhangsan@gmail.com");
        15:         requestData.Add("Address.Province", "江蘇");
        16:         requestData.Add("Address.City", "蘇州");
        17:         requestData.Add("Address.District", "工業(yè)園區(qū)");
        18:         requestData.Add("Address.Street", "星湖街328號");
        19:         return new NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);
        20:     }    
        21:  
        22:     public void Index()
        23:     {
        24:         InvokeAction("Action");
        25:     }
        26:  
        27:     public void Action(Contact foo, Contact bar)
        28:     {
        29:         Response.Write("Foo<br/>");
        30:         Response.Write(string.Format("{0}: {1}<br/>", "Name", foo.Name));
        31:         Response.Write(string.Format("{0}: {1}<br/>", "PhoneNo", foo.PhoneNo));
        32:         Response.Write(string.Format("{0}: {1}<br/>", "EmailAddress", foo.EmailAddress));
        33:         Response.Write(string.Format("{0}: {1} {2} {3} {4}<br/><br/>", "Address", 
        34:            foo.Address.Province, foo.Address.City, foo.Address.District, 
        35:            foo.Address.Street));
        36:  
        37:         Response.Write("Bar<br/>");
        38:         Response.Write(string.Format("{0}: {1}<br/>", "Name", bar.Name));
        39:         Response.Write(string.Format("{0}: {1}<br/>", "PhoneNo", bar.PhoneNo));
        40:         Response.Write(string.Format("{0}: {1}<br/>", "EmailAddress", bar.EmailAddress));
        41:         Response.Write(string.Format("{0}: {1} {2} {3} {4}<br/>", "Address", 
        42:             bar.Address.Province, bar.Address.City, bar.Address.District, 
        43:             bar.Address.Street)); 
        44:     }
        45: }

      通過GetValueProvider方法提供的依然是一個NameValueCollectionValueProvider對象,我們將一個Contact對象包含的信息包含在它對應(yīng)的NameValueCollection對象中。對于添加到NameValueCollection中的針對Contact對象的某個屬性的數(shù)據(jù)條目,我們按照上面介紹的匹配規(guī)則對其命名。運(yùn)行我們的實(shí)例程序,我們會在瀏覽器中得到如下所示的輸出結(jié)果,我們從中可以看到Action方法的兩個參數(shù)foo和bar通過我們自定義的DefaultModelBinder進(jìn)行了正確地綁定,并且它們具有相同的值。

         1: Foo
         2: Name: 張三
         3: PhoneNo: 123456789
         4: EmailAddress: zhangsan@gmail.com
         5: Address: 江蘇 蘇州 工業(yè)園區(qū) 星湖街328號
         6:  
         7: Bar
         8: Name: 張三
         9: PhoneNo: 123456789
        10: EmailAddress: zhangsan@gmail.com
        11: Address: 江蘇 蘇州 工業(yè)園區(qū) 星湖街328號

      之所以同一個Action方法中兩個相同類型的參數(shù)會綁定相同的數(shù)據(jù),使緣于之前介紹的去除前綴的后備Model綁定機(jī)制。由于請求數(shù)據(jù)中并不包含針對某個參數(shù)的前綴,所以在針對參數(shù)名稱作為前綴的Model綁定失敗的情況下,后備Model綁定會前綴為空字符串的情況下再次進(jìn)行。

         1: public class HomeController : Controller
         2: {
         3:     //其他成員
         4:     private IValueProvider GetValueProvider()
         5:     {
         6:         NameValueCollection requestData = new NameValueCollection();
         7:         requestData.Add("foo.Name", "Foo");
         8:         requestData.Add("foo.PhoneNo", "123456789");
         9:         requestData.Add("foo.EmailAddress", "Foo@gmail.com");
        10:  
        11:         requestData.Add("bar.Name", "Bar");
        12:         requestData.Add("bar.PhoneNo", "987654321");
        13:         requestData.Add("bar.EmailAddress", "Bar@gmail.com");
        14:         return new NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);
        15:     }
        16:  
        17:     public void Action(Contact foo, Contact bar)
        18:     {
        19:         Response.Write("Foo<br/>");
        20:         Response.Write(string.Format("{0}: {1}<br/>", "Name", foo.Name));
        21:         Response.Write(string.Format("{0}: {1}<br/><br/>", "PhoneNo", foo.PhoneNo));
        22:         Response.Write(string.Format("{0}: {1}<br/>", "EmailAddress", foo.EmailAddress));
        23:  
        24:         Response.Write("Bar<br/>");
        25:         Response.Write(string.Format("{0}: {1}<br/>", "Name", bar.Name));
        26:         Response.Write(string.Format("{0}: {1}<br/>", "PhoneNo", bar.PhoneNo));
        27:         Response.Write(string.Format("{0}: {1}<br/>", "EmailAddress",   bar.EmailAddress));
        28:     }
        29: }

      在如上所示的代碼中,我們?yōu)镹ameValueCollectionValueProvider設(shè)置了基于“foo”和“bar”的前綴的兩套數(shù)據(jù),目的在為Action方法的foo和bar參數(shù)提供不同的數(shù)據(jù)。運(yùn)行我們的程序后會在瀏覽器上得到如下所示的輸出結(jié)果,可以看出Action方法的兩個參數(shù)被綁定了不同的值。

         1: Foo
         2: Name: Foo
         3: PhoneNo: 123456789
         4: EmailAddress: Foo@gmail.com
         5:  
         6: Bar
         7: Name: Bar
         8: PhoneNo: 987654321
         9: EmailAddress: Bar@gmail.com

       

      通過實(shí)例模擬ASP.NET MVC的Model綁定的機(jī)制:簡單類型+復(fù)雜類型
      通過實(shí)例模擬ASP.NET MVC的Model綁定的機(jī)制:數(shù)組
      通過實(shí)例模擬ASP.NET MVC的Model綁定的機(jī)制:集合+字典

      posted @ 2012-05-23 08:20  Artech  閱讀(15734)  評論(14)    收藏  舉報(bào)
      主站蜘蛛池模板: 中文字幕乱码在线人视频| 亚洲国产精品第一区二区| CAOPORN免费视频国产| 国产成人人综合亚洲欧美丁香花| 乱人伦人妻中文字幕不卡| 亚洲综合无码明星蕉在线视频| 泽库县| av无码久久久久不卡网站蜜桃| 99久久无码私人网站| 下面一进一出好爽视频| 亚洲一区二区三区啪啪| 少妇xxxxx性开放| 影音先锋人妻啪啪av资源网站| 国产精品亚洲一区二区z| 国产明星精品无码AV换脸| 少妇被粗大的猛烈进出69影院一 | 91久久夜色精品国产网站| 欧洲熟妇熟女久久精品综合| 精品久久久久久无码人妻蜜桃| 国产精品v欧美精品∨日韩| 久久亚洲精精品中文字幕| 人人妻人人妻人人片av | 波多野结衣高清一区二区三区 | 亚洲av永久无码精品网站| 免费人成网站免费看视频| 久久精品国产亚洲av天海翼| Y111111国产精品久久久| 亚洲国产午夜精品福利| 欧美熟妇乱子伦XX视频| 亚洲欧洲av人一区二区| 377人体粉嫩噜噜噜| 成人国产精品一区二区不卡| 强奷漂亮人妻系列老师| 四虎永久地址www成人| 中文字幕午夜福利片午夜福利片97 | 毛片内射久久久一区| 黑色丝袜脚交视频麻豆| 亚洲熟女精品一区二区| 91精品国产老熟女在线| 在线 欧美 中文 亚洲 精品| 色综合网天天综合色中文|