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

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

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

      委托

      委托

      一、什么是委托,委托的本質是什么?

      1. 跟方法有點類似,有參數,返回值,訪問修飾符+delegate --委托--特殊的方法?
      2. 委托的本質是什么?是方法嗎?
      3. 反編譯試試:發現定義的委托-----再CustomDelegate ----有對應的class
      4. 委托的本質是什么?---Class(類),繼承自一個MulticastDelegate的特殊類,自己在定義類的時候,是無法繼承的。包含的有構造函數和方法。
      5. 委托既然是一個類---怎么使用這個類?new ---調用方法/屬性
      
         public class DelegateDemo
         {
            
             public delegate void NoReturnWithoutParaout();
             public delegate void NoReturnWithParaout(out int x);
             public delegate void NoReturnWithParaRef(ref int x);
             public delegate int WithReturnWithoutPara();
             public delegate int WithReturnWithPara(int x, int y);
      
             public static void  NoReturnWithoutParaoutfunc()
             {
                 Console.WriteLine("NoReturnWithoutParaoutfunc called!");
             }
      
             public static void NoReturnWithParaoutfunc(out int x)
             {
                 x = 100;
                 Console.WriteLine("NoReturnWithParaoutfunc called!");
             }
      
             public static void NoReturnWithParaReffunc(ref int x)
             {
                 x = 100;
                 Console.WriteLine("NoReturnWithParaReffunc called!");
             }
      
             public static int WithReturnWithoutParafunc()
             {
                 Console.WriteLine("WithReturnWithoutParafunc called!");
                 return 100;
             }
      
             public static int WithReturnWithParafunc(int x, int y)
             {
                 Console.WriteLine("WithReturnWithParafunc called!");
                 return x + y;
             }
      
      
         }
      
      

      二、委托的實例化

      1. ILSpy反編譯--委托的本質其實是一個類
      2. 委托本質是一個類,這個類的構造參數--Method方法
      3. 委托可以通過New來實例化,要求傳遞一個和這個委托的參數和返回值完全匹配的方法,委托有什么參數(幾個,什么類型)---完全匹配
      4. 委托的實例---可以直接指向和這個委托參數+返回值完全匹配的方法;--語法糖--編譯器給我們提供便捷功能new省略掉了。
      5. 執行委托實例的Invoke方法--去執行這個委托實例化的指向的這個方法---執行方法;
      6. 就可以執行這個實例內部的三個方法
      7. 多種實例化:new、指向一個方法、指向一個lambda表達式
      
      NoReturnWithoutParaout noReturnWithoutParaout = new NoReturnWithoutParaout(NoReturnWithoutParaoutfunc);
      
      noReturnWithoutParaout();
      
      
      

      三、委托的作用和意義

      現在有一個學生類

       {
           public int Id { get; set; }
           public string Name { get; set; }
           public int ClassId { get; set; }
           public int Age { get; set; }
           public Student() { }
      
           public void SayHi()
           {
               Console.WriteLine("大家好,我是學員,我叫{0}", this.Name);
           }
           public void Study()
           {
               Console.WriteLine("學習.net高級班公開課");
           }
      
           public static void StudyAdvanced()
           {
               Console.WriteLine("學習.net高級班vip課");
           }
       }
      

      我們可以調用一下學生中的方法

      {
          Student stu = new Student()
          {
              Id = 1,
              Name = "張三",
              ClassId = 1,
              Age = 18
          };
          stu.SayHi();
      }
      

      我們現在多了一個這樣的使用場景的問題
      場景1. 學生分類?武漢人、上海人、廣東人--三種不同類型的人;問候的口語不一樣;
      定義三種人:a.武漢 b.上海 c.廣東人
      問好的方式有多種;
      WuHan 人: 吃了么?
      GuanDong 人:靚仔/靚女~ 雷猴!
      BeiJing 人: 你好!

      問題一:如果想要增加一個地方的人;

      解決方案一:(多增加幾個方法)可以為每一個地方的人,各自定義一個方法

       public void SayShangHai()
       {
           Console.WriteLine("招招手~");
           Console.WriteLine("儂好?");
       }
      
       public void SayHiWuHan()
       {
           Console.WriteLine("招招手~");
           Console.WriteLine("吃了么?");
       }
      
       public void SayHiGuanDong()
       {
           Console.WriteLine("招招手~");
           Console.WriteLine("靚仔/靚女~ 雷猴!");
       }
      
       public void SayHiBeiJing()
       {
           Console.WriteLine("招招手~");
           Console.WriteLine("你好!");
       }
      
      

      解決方案二:(傳遞參數來判斷)

        /// 傳入參數,分辨類型----使用枚舉--避免調用方出錯;
        /// 不同的類型給不同的邏輯
      
      public enum UserType
      {
          Wuhan = 1, 
          GuangDong = 2,
          BeiJing = 3
      }
      
         public void SayHi(UserType userType) //1.   哪兒的人  2 哪兒的人
         {
             Console.WriteLine("招招手~");  //只需要一句代碼搞定了
             switch (userType)
             {
                 case UserType.Wuhan:
                     Console.WriteLine("吃了么?");
                     break;
                 case UserType.BeiJing:
                     Console.WriteLine("你好!");
                     break;
                 case UserType.GuangDong:
                     Console.WriteLine("靚仔/靚女~ 雷猴!");
                     break;
                 default:
                     throw new Exception("No userType");
      
             }
         }
      

      點評:
      方案一:更好---每個方案,可以相互獨立,互不干擾,邏輯沒有解耦;滿足單一職責;
      方案二:耦合在一起,如果有需求的升級,可能需要修改原有的方案,代碼可能會不穩定

      問題二:如果我想要增加一些公共的業務邏輯呢?問好前---伴隨一個動作---“招招手”

      再比較:方案二更有有優勢了; 只需要增加一句,就可以覆蓋所有的人;
      方案一出現了重復代碼;

      有沒有一個完美方案呢?

      自上而下比較:邏輯單一,邏輯解耦,職責單一,保證代碼的穩定性;
      如何寫?
      思路:傳遞參數枚舉---分辨不同地方的人----給出不同的業務邏輯-----(傳枚舉usertype---選擇邏輯)----直接傳遞邏輯唄; 邏輯在哪兒? 封裝成一個方法; 其實就是需要傳遞一個方法;
      問題:如何把方法當做參數來進行傳遞??? 啥??? 當然是委托;

       public delegate void DoHandlerDelegate();
       public void SayHiPerfect(DoHandlerDelegate doHandler)
       {
           Console.WriteLine("保持微笑~~");
           doHandler.Invoke();
       }
      
      

      在主程序執行的時候

      
      Console.WriteLine("通過委托傳遞邏輯 \r\n");
      DoHandlerDelegate doHandlerWuhan = new DoHandlerDelegate(student.SayHiWuHan);
      student.SayHiPerfect(doHandlerWuhan);
      
      DoHandlerDelegate doHandlerBeiJin = new DoHandlerDelegate(student.SayHiBeiJing);
      student.SayHiPerfect(doHandlerBeiJin);
      
      DoHandlerDelegate doHandlerGuangDong = new DoHandlerDelegate(student.SayHiGuanDong);
      student.SayHiPerfect(doHandlerGuangDong);
      

      問題一:增加一個上海人 --- 增加了一個方案; 方法單一; 方法相互獨立,互不干擾;--穩定性,邏輯解耦

      問題二:增加一個公共的業務邏輯,只需要在SayHiPerfect 增加一個動作即可;去掉重復代碼;

      
              public void SayShangHai()
              {
                  Console.WriteLine("招招手~");
                  Console.WriteLine("儂好?");
              }
      
      

      主程序中

      DoHandlerDelegate doHandlerShangHi = new DoHandlerDelegate(student.SayShangHai);
      student.SayHiPerfect(doHandlerShangHi); 
      
      

      委托的價值:
      1.邏輯解耦,代碼的職責單一
      2.去掉重復代碼

      建議: 如果代碼中出現了嚴重的耦合----考慮使用委托來解決下
      如果代碼中,出現了大量的重復代碼----考慮使用委托來解決下

      四、框架內置的委托Action/Func

      這里我們定義了兩個相同的委托,

      public delegate void DoGodDelegate(object? o);
      public delegate void ParameterizedThreadStart(object? o);
      

      我們在單獨使用這2個委托的時候,并不會遇到什么問題,
      我們可以發現無論是doRichard 還是threadStart 執行委托,都是執行的同一個方法;
      兩個委托做的事兒是一模一樣;

      問題

      Thread thread = new Thread(threadStart);
      //Thread thread1 = new Thread(doRichard); //不允許的;問題:在兩個結構,功能完全相同的委托;  有可能不能通用的;  不太合理???
      

      Why?? 類型不一樣~~
      委托的本質是一個類, 多個委托就是多個不同的類, 這些沒有繼承關系,所以不能用;
      以上問題、微軟也發現了;
      為了能夠讓委托能通用, 為了不用定義過多的委托;
      微軟提供了兩個類功的委托: Action/Func

      Action: 應對了沒有返回值的委托場景;
      可有可無參數,一定沒有返回值的委托;最多可以有16個參數~~ 16個泛型版本
      如果想要有17個參數的委托呢?(自己擴展)

       Action<int> action1 = new Action<int>(s => {  }); //接收一個int類型參數,沒有返回值
       Action<int,string> action2 = new Action<int, string>((i,s) => { }); //接收一個int類型參數,沒有返回值
       Action<int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object> action3 = null;
       Action<int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object,int> action4 = null;
      

      這是一個沒有返回值的通用委托---如果所有的人需要使用沒有返回值的委托的時候,都用Action, 不用定義委托;委托都是同一個類型; 就可以通用了;
      微軟既然提供這個委托,自然是希望我們在以后的編碼中,都盡可能使用這些,這樣就可以統一了委托的類型;
      對于以前定義的委托呢? 咋辦? 解決不了~~ 這些被稱為技術上的歷史包袱,丟不掉~~ 以后在使用委托的時候,就不要自己定義了,直接使用現有提供的委托即可~~

      委托要有返回值呢?
      Func:多版本的委托:應對了有返回值的情況;
      一定有返回值的委托;泛型委托Func中的最后一個類型參數,是作為返回值的類型;前面的類型參數,是作為委托的參數;也提供了最多可以有16個參數;
      如果需要有17個參數,且有返回值的委托呢? 可以擴展下唄;

      Func<int> func = new Func<int>(() => { return 10; }); //一個返回值的委托,沒有參數;
      Func<int, string> func1 = new Func<int, string>(s => { return "R"; });
      Func<int,string,DateTime,object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, string> func2 = null;
      
      //17個參數;
      Func<int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime, object, int, string, DateTime,object, object, string> func3 = null;
      
      
       public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
       public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
      

      五、委托的嵌套使用,ASP.NET CORE中間件的核心設計----委托的多層嵌套

      這里創建一個很基礎的一個類

       public class DelegateExtension
       {
           public static void Show()
           {
               InvokeAction invokeAction = new InvokeAction();
               {
                   
               }
      
      
           }
       }
      
       public class InvokeAction {
           public void ExeMethod()
           {
               Console.WriteLine("Exec ExeMethod");
           }
       }
      

      問題:想要去在Invoke.Show方法前后,擴展一些業務邏輯.

      這里根據我們之前上面拓展出來的知識可以寫出來這樣的代碼

          public static void Show()
          {
              InvokeAction invokeAction = new InvokeAction();
              {
                  Action action = new Action(invokeAction.ExeMethod);
                  //再次定義委托
                  {
                      Func<Action, Action> action2 = new Func<Action, Action>(ExeNextMethod006);
                      Action action3 = action2.Invoke(action);
                      action = action3;
      
                      Func<Action, Action> action4 = new Func<Action, Action>(ExeNextMethod005);
                      Action action5 = action4.Invoke(action);
                      action = action5;
      
      
                      Func<Action, Action> action6 = new Func<Action, Action>(ExeNextMethod004);
                      Action action7 = action6.Invoke(action);
                      action = action7;
      
      
                      Func<Action, Action> action8 = new Func<Action, Action>(ExeNextMethod003);
                      Action action9 = action8.Invoke(action);
                      action = action9;
      
      
                      Func<Action, Action> action10 = new Func<Action, Action>(ExeNextMethod002);
                      Action action11 = action10.Invoke(action);
                      action = action11;
      
                      Func<Action, Action> action12 = new Func<Action, Action>(ExeNextMethod001);
                      Action action13 = action12.Invoke(action);
                      action = action13;
      
                      action.Invoke();
                  }
                  
              }
          }
      
          public static Action ExeNextMethod001(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod001 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod001 End");
              });
          }
      
          public static Action ExeNextMethod002(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod002 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod002 End");
              });
          }
      
          public static Action ExeNextMethod003(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod003 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod003 End");
              });
          }
          public static Action ExeNextMethod004(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod004 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod004 End");
              });
          }
      
          public static Action ExeNextMethod005(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod005 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod005 End");
              });
          }
      
          public static Action ExeNextMethod006(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod006 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod006 End");
              });
          }
      }
      
      
      
      public class InvokeAction {
          public void ExeMethod()
          {
              Console.WriteLine("Exec ExeMethod");
          }
      }
      
      

      我希望無限制的 增加擴展業務邏輯;
      再增加一個--定義方法,通過委托包裝后去當做參數傳遞;
      現在的代碼已經做到了
      1.已經做到了職責的單一;
      2.但是當前這個 DelegateExtension.Show 方法不太穩定,如果要增加一環,我需要修改DelegateExtension.Show方法
      思路:可以把要執行的業務邏輯----特性--封裝到特性中去;

      public static void Show()
      {
          InvokeAction invokeAction = new InvokeAction();
          {
              
             {
                  Type type= typeof(InvokeAction);
                  MethodInfo method = type.GetMethod("ExeMethod");
      
                  ExecNextMethod001Attribute attribute1 = method.GetCustomAttribute<ExecNextMethod001Attribute>();
                  Action action=new Action(()=> { method.Invoke(invokeAction, null); });
                  action=attribute1.Do(action);
      
                  ExecNextMethod002Attribute attribute2 = method.GetCustomAttribute<ExecNextMethod002Attribute>();
                  action = attribute2.Do(action);
      
                  ExecNextMethod003Attribute attribute3 = method.GetCustomAttribute<ExecNextMethod003Attribute>();
                  action = attribute3.Do(action);
      
                  ExecNextMethod004Attribute attribute4 = method.GetCustomAttribute<ExecNextMethod004Attribute>();
                  action = attribute4.Do(action);
      
                  action.Invoke();
      
              }
              
          }
      }
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod001Attribute: Attribute
      {
         public Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod001 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod001 End");
              });
          }
      }
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod002Attribute : Attribute
      {
          public Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod002 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod002 End");
              });
          }
      }
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod003Attribute : Attribute
      {
          public Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod003 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod003 End");
              });
          }
      }
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod004Attribute : Attribute
      {
          public Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod004 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod004 End");
              });
          }
      }
      
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod005Attribute : Attribute
      {
          public Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod005 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod005 End");
              });
          }
      }
      
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod006Attribute : Attribute
      {
          public Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod006 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod006 End");
              });
          }
      }
      

      思路:因為類型不一樣,所以只能一個一個的判斷;
      如果能一次獲取所有特性(矛盾,類型不一樣,沒有辦法一次獲取所有;????統一類型,如何統一類型?? 來一個父類,讓特性繼承父類,然后在獲取特性的時候,通過父類獲取;):放在一個集合中,要逐個的調用特性的Do方法來包裝委托的話,就可以循環執行;

      public static void Show()
      {
          InvokeAction invokeAction = new InvokeAction();
          Type type = typeof(InvokeAction);
          MethodInfo method = type.GetMethod("ExeMethod");
      
          Action action = new Action(() => { method.Invoke(invokeAction, null); });
      
          IEnumerable<ExecNextMethodAbstractAttribute> attributellist = method.GetCustomAttributes<ExecNextMethodAbstractAttribute>();
      
          foreach (var attribute in attributellist.Reverse())
          {
              action = attribute.Do(action);
          }
          action.Invoke();
      
      
      
      }
      
      [AttributeUsage(AttributeTargets.Method)]
      public abstract class ExecNextMethodAbstractAttribute : Attribute
      {
          public abstract Action Do(Action action);
      
      }
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod001Attribute : ExecNextMethodAbstractAttribute
      {
          public override Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod001 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod001 End");
              });
          }
      }
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod002Attribute : ExecNextMethodAbstractAttribute
      {
          public override Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod002 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod002 End");
              });
          }
      }
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod003Attribute : ExecNextMethodAbstractAttribute
      {
          public override Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod003 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod003 End");
              });
          }
      }
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod004Attribute : ExecNextMethodAbstractAttribute
      {
          public override Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod004 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod004 End");
              });
          }
      }
      
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod005Attribute : ExecNextMethodAbstractAttribute
      {
          public override Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod005 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod005 End");
              });
          }
      }
      
      
      [AttributeUsage(AttributeTargets.Method)]
      public class ExecNextMethod006Attribute : ExecNextMethodAbstractAttribute
      {
          public override Action Do(Action action)
          {
              return new Action(() =>
              {
                  Console.WriteLine("Exec ExeNextMethod006 Start");
                  action();
                  Console.WriteLine("Exec ExeNextMethod006 End");
              });
          }
      }
      

      這樣就可以讓我們自己在搭建框架的時候(支持了業務的擴展---AOP擴展---裝飾器模式的番外篇),可以讓程序員在使用我們這個框架的時候,更加聚焦業務邏輯;
      可以動態增加業務邏輯;

      六、多播委托/觀察者模式

      委托還可以通過+= 把更多的方法包裝到委托中來,形成一個方法的執行鏈子
      在執行委托的時候,可以按照+=的順序,把方法逐個執行;
      也提供了-= 操作,可以按照順序把方法從方法鏈子中,依次移除;移除按照順序依次移除,只要是匹配移除一個之后,就不在繼續移除了;如果要移除的方法在,委托中不存在,-=就不做任何操作;

      委托在+=,-=可以操作哪些方法呢?

      • 靜態方法
      • 實例方法
      • lamdba表達式
      • 普通方法
       public void Show()
       {
           {
               Action action = new Action(DoNothing);
              
               action += DoNothing;
               action += DoNothing;
               action += DoNothing;
               action += DoNothing;                
               action -= DoNothing;
               
               action.Invoke();
           }
      
           //委托在+=  、 -=可以操作哪些方法呢?
           {
               Action action = new Action(DoNothing);
               action += DoNothingStatic; //+=靜態方法
               action += new Student().Study; //+=實例方法
               action += () => { Console.WriteLine("this is Lambda"); };
      
               //action.Invoke();  //都會依次執行
      
               action -= DoNothing;    //普通方法
               action -= DoNothingStatic;  //靜態方法
               action -= new Student().Study;  //實例方法
               action -= () => { Console.WriteLine("this is Lambda"); }; //Lambda 表達式
      
               action.Invoke();
           }
      
       }
       private void DoNothing()
       {
           Console.WriteLine("This is DoNothing");
       }
        
       private static void DoNothingStatic()
       {
           Console.WriteLine("This is DoNothingStatic");
       }
      
      posted @ 2024-03-01 16:46  飄雨的河  閱讀(166)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲一区二区三区四区| 日本真人做爰免费视频120秒 | 龙口市| 亚洲区成人综合一区二区| 亚洲中文字幕成人综合网| 怡春院久久国语视频免费| 一区二区亚洲人妻精品| 国产免费视频一区二区| 国产美女精品自在线拍免费| 亚洲中文字幕无码久久精品1 | 无码福利写真片视频在线播放| 亚洲精品三区二区一区一| 精品精品亚洲高清a毛片| 亚洲一区二区中文av| 亚洲日韩国产中文其他| 99网友自拍视频在线| 亚洲偷自拍国综合| 一边添奶一边添p好爽视频| 久久精品国产九一九九九| 少妇人妻偷人精品系列| 国产成人一区二区三区影院动漫| 国产av一区二区三区综合| 亚洲最大日韩精品一区| 日日碰狠狠添天天爽五月婷| 国产激情一区二区三区在线| 国产综合视频一区二区三区| 开江县| 国产情侣激情在线对白| 又爽又黄又无遮挡的激情视频| 招远市| 日韩伦理片| 久久日韩精品一区二区五区| 人妻日韩精品中文字幕| 五月天天天综合精品无码| 在线观看AV永久免费| 亚洲国产日韩一区三区| 国产精品久久久久影院色| 免费看久久妇女高潮a| 丰满少妇内射一区| 国产精品线在线精品| 国产激情艳情在线看视频|