精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解C#編程中的反射機制與方法

開發 后端
本文將為大家詳細講解C#中的反射,也就是Reflection。反射提供一種編程的方式,讓程序員可以在程序運行期獲得這幾個組成部分的相關信息。

編輯推薦《C#實用基礎教程

Reflection,中文翻譯為反射。這是.Net中獲取運行時類型信息的方式,.Net的應用程序由幾個部分:‘程序集(Assembly)’、‘模塊(Module)’、‘類型(class)’組成,而反射提供一種編程的方式,讓程序員可以在程序運行期獲得這幾個組成部分的相關信息,例如:Assembly類可以獲得正在運行的裝配件信息,也可以動態的加載裝配件,以及在裝配件中查找類型信息,并創建該類型的實例。Type類可以獲得對象的類型信息,此信息包含對象的所有要素:方法、構造器、屬性等等,通過Type類可以得到這些要素的信息,并且調用之。MethodInfo包含方法的信息,通過這個類可以得到方法的名稱、參數、返回值等,并且可以調用之。諸如此類,還有FieldInfo、EventInfo等等,這些類都包含在System.Reflection命名空間下。

一、Type類于獲取類型信息

System.Type 類對于反射起著核心的作用。當反射請求加載的類型時,公共語言運行庫將為它創建一個 Type。您可以使用 Type 對象的方法、字段、屬性和嵌套類來查找有關該類型的所有信息。
大家運行一下下面的代碼根據結果分析一下就能比較清楚的理解Type了

獲取類型信息

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass m = new MyClass();
            Type type = m.GetType();
            Console.WriteLine("類型名:" + type.Name);
            Console.WriteLine("類全名:"+type.FullName);
            Console.WriteLine("命名空間名:"+type.Namespace);
            Console.WriteLine("程序集名:"+type.Assembly);
            Console.WriteLine("模塊名:"+type.Module);
            Console.WriteLine("基類名:"+type.BaseType);
            Console.WriteLine("是否類:"+type.IsClass);
            Console.WriteLine("類的公共成員:");
            MemberInfo[] memberInfos = type.GetMembers();//得到所有公共成員
            foreach (var item in memberInfos)
            {
                Console.WriteLine("{0}:{1}",item.MemberType,item);
            }
        }
       
    }
    class MyClass
    {
        public string m;
        public void test()
        { }
        public int MyProperty { get; set; }

    }
}

二、獲取程序集元數據

Assembly類定義了一個程序集,它是一個可重用、無版本沖突并且可自我描述的公共語言運行庫應用程序構造塊。因為程序集中是使用元數據進行自我描述的,所以我們就能通過其元數據得到程序集內部的構成。結合Assembly和反射能夠獲取程序集的元數據,但是首先要將程序集裝入內存中。可以使用Assembly類的多種靜態Load方法加載程序集。

下面的程序顯示程序集的信息


public static void Main()
        {
            //獲取當前執行代碼的程序集
            Assembly assem = Assembly.GetExecutingAssembly();

            Console.WriteLine("程序集全名:"+assem.FullName);
            Console.WriteLine("程序集的版本:"+assem.GetName().Version);
            Console.WriteLine("程序集初始位置:"+assem.CodeBase);
            Console.WriteLine("程序集位置:"+assem.Location);
            Console.WriteLine("程序集入口:"+assem.EntryPoint);

            Type[] types = assem.GetTypes();
            Console.WriteLine("程序集下包含的類型:");
            foreach (var item in types)
            {
                Console.WriteLine("類:"+item.Name);
            }
           
        }

三、動態加載類型

早綁定是在編譯時綁定對象類型,而晚綁定是在運行時才綁定對象的類型。利用反射可以實現晚綁定,即動態加載類型,并調用他們的方法,下邊是MSDN中的一個例子,詳細的解釋信息見注釋

動態加載類型

namespace ConsoleApplication2
{
    public class Example
    {
        private int factor;
        public Example(int f)
        {
            factor = f;
        }

        public int SampleMethod(int x)
        {
            Console.WriteLine("\nExample.SampleMethod({0}) executes.", x);
            return x * factor;
        }

        public static void Main()
        {
            //獲取當前執行代碼的程序集
            Assembly assem = Assembly.GetExecutingAssembly();

            Console.WriteLine("Assembly Full Name:");
            Console.WriteLine(assem.FullName);

            // The AssemblyName type can be used to parse the full name.
            AssemblyName assemName = assem.GetName();
            Console.WriteLine("\nName: {0}", assemName.Name);
            Console.WriteLine("Version: {0}.{1}",
                assemName.Version.Major, assemName.Version.Minor);
            Console.WriteLine("\nAssembly CodeBase:");
            Console.WriteLine(assem.CodeBase);
            // 從程序集眾創建一個Example實例并且用object類型的引用o指向它,同時調用一個輸入參數的構造函數
            Object o = assem.CreateInstance("ConsoleApplication2.Example", false,
                BindingFlags.ExactBinding,
                null, new Object[] { 2 }, null, null);

            //構造Example類的一個晚綁定的方法SampleMethod 
            MethodInfo m = assem.GetType("ConsoleApplication2.Example").GetMethod("SampleMethod");
            //調用剛才實例化好的Example對象o中的SampleMethod方法,傳入的參數為42
            Object ret = m.Invoke(o, new Object[] { 42 });
            Console.WriteLine("SampleMethod returned {0}.", ret);

            Console.WriteLine("\nAssembly entry point:");
            Console.WriteLine(assem.EntryPoint);
        }
    }

反射特性:

[Table(Name="dbo.[User]")]
public partial class User
{

當C#編譯器發現這個屬性有一個特性Table時,首先會把字符串Attribute添加到這個名稱的后面,形成一個組合名稱TableAttribute,然后在其搜索路徑的所有命名空間中搜索有相同類名的類。但要注意,如果該特性名結尾是Attribute,編譯器就不會把該字符串加到組合名稱中。所有的特性都是從System.Attribute類型上面派生的。

接著我們來看一下Table特性的定制格式

[AttributeUsageAttribute(AttributeTargets.Class,Inherited=true,AllowMultiple=false)]
public class TalbeAttribute:Attribute
{

在定義類型時使用System.AttributeUsage特性來表明這個自定義特性的使用范圍,這里使用了Class樣式,表示TableAttribute特性只能用在其它的Class類型前面,若放置在Interface或Struct類型前面,或者放在對象成員的前面則會出現編譯錯誤。這里還是用語句 AllowMultiple=false 語句來表明對于一個類型,該特性只能用一次,若一個Class類型前面出現多個TableAttribute,則會出現編譯錯誤。若設置AllowMultiple=true,則該特性可以多次定義,也就是一個Class類型前面可以出現多個相同類型的特性。不過這里我們假設一個對象只能映射到一個數據表上,沒有多重映射,因此就指明對同一個類型該特性不能多次使用。Inherited參數設定為true,就表示應用到類或接口上的特性也可以自動應用到所派生的類或接口上。

我們再看一下定制TalbeAttribute特性的完整例子:

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    public class TableAttribute : Attribute
    {
        //保存表名的字段
        private string _tableName;

        public TableAttribute()
        {
        }

        public TableAttribute(string tableName)
        {
            this._tableName = tableName;
        }

        ///


        /// 映射的表名(表的全名:模式名.表名)
        ///

        public string TableName
        {
            set
            {
                this._tableName = value;
            }
            get
            {
                return this._tableName;
            }
        }
    }

特性也是一個Class類型,可以有多個構造函數,就像C#的new語句一樣,我們向類型附加特性時可以使用不同的初始化參數來指明使用特性的那個構造函數。我們附加特性時還可以使用“屬性名=屬性值”的方法來直接指明特性的屬性值。該特性中定義了一個TableName屬性,該屬性就是被修飾的對象所映射的數據庫表的名稱。

下面我們舉一個使用特性來進行O/RMapping的例子,也就是將對象轉化成Sql語句

用戶類:

User類

    [Table("User")]
    public class User
    {
        [Colum("userID", DbType = DbType.Int32)]
        public int UserID { get; set; }
        [Colum("UserName", DbType = DbType.String)]
        public string UserName { get; set; }
    }

表特性

[AttributeUsageAttribute(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    public class TableAttribute : Attribute
    {
        //保存表名的字段
        private string _tableName;

        public TableAttribute()
        {
        }

        public TableAttribute(string tableName)
        {
            this._tableName = tableName;
        }

        ///


        /// 映射的表名(表的全名:模式名.表名)
        ///

        public string TableName
        {
            set
            {
                this._tableName = value;
            }
            get
            {
                return this._tableName;
            }
        }
    }


列特性: 

[AttributeUsageAttribute(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public class ColumAttribute : Attribute
    {
        private string _columName;

        private DbType _dbType ;


        public ColumAttribute()
        {
        }

        public ColumAttribute(string columName)
            : this()
        {
            this._columName = columName;
        }
    
        public ColumAttribute(string columName, DbType dbType)
            : this(columName)
        {
            this._dbType = dbType;
        }

        //列名
        public virtual string ColumName
        {
            set
            {
                this._columName = value;
            }
            get
            {
                return this._columName;
            }
        }

        //描述一些特殊的數據庫類型
        public DbType DbType
        {
            get { return _dbType; }
            set { _dbType = value; }
        }

    }

 

 

ORMHelp
 public class ORMHelp
    {
        public void Insert(object table)
        {
            Type type = table.GetType();
            //定義一個字典來存放表中字段和值的對應序列
            Dictionary columValue = new Dictionary();
            StringBuilder SqlStr=new StringBuilder();
            SqlStr.Append("insert into ");
            //得到表名子
            TableAttribute temp = (TalbeAttribute)type.GetCustomAttributes(typeof(TalbeAttribute), false).First();
            SqlStr.Append(temp.TableName);
            SqlStr.Append("(");
            PropertyInfo[] Propertys=type.GetProperties();
            foreach (var item in Propertys)
            {
                object[] attributes = item.GetCustomAttributes(false);
                foreach (var item1 in attributes)
                {
                    //獲得相應屬性的值
                   string value= table.GetType().InvokeMember(item.Name, System.Reflection.BindingFlags.GetProperty, null, table, null).ToString();
                    ColumAttribute colum = item1 as ColumAttribute;
                    if (colum != null)
                    {
                        columValue.Add(colum.ColumName,value);
                    }
                }
            }
            //拼插入操作字符串
            foreach (var item in columValue)
            {
                SqlStr.Append(item.Key);
                SqlStr.Append(",");

            }
            SqlStr.Remove(SqlStr.Length-1, 1);
            SqlStr.Append(") values('");
            foreach (var item in columValue)
            {
                SqlStr.Append(item.Value);
                SqlStr.Append("','");


            }
            SqlStr.Remove(SqlStr.Length - 2, 2);
            SqlStr.Append(")");
            Console.WriteLine(SqlStr.ToString());


        }
    }
SqlStr中的內容為insert into User(userID,UserName) values('1','lfm')

前端使用代碼:

前端代碼

static void Main(string[] args)
        {
            ORMHelp o = new ORMHelp();
            User u = new User() { UserID=1,UserName="lfm"};
            o.Insert(u);
        }

應用

例子這個東西其實挺難弄得,弄個簡單的,雖然能說明問題但卻容易讓人覺得沒實用價值,弄個有實用價值卻又往往牽扯很多別的技術甚至牽扯很多業務邏輯,看起來很復雜很難懂。在這里我盡量追求幾個有實用價值又不復雜的例子。

#p#

1、使用反射通過讀取配置文件來動態的創建相關類的對象

我們先來看看Main函數和需要動態加載的對象在同一個程序集的情況

結構圖:

接口

interface ILog
    {
        bool Write(string message);
        bool Write(Exception ex);
    }
TextFileLog
class TextFileLog : ILog
    {
        public bool Write(string message)
        {
            string fileDir = ConfigurationManager.AppSettings["LogTarget"].ToString();
            using (StreamWriter w = File.AppendText(fileDir))
            {
                // w.Write(" Log Entry : ");
                w.WriteLine("發生時間{0}", DateTime.Now.ToLocalTime().ToString());
                w.WriteLine("日志內容為:{0}", message);
                w.WriteLine("-------------------------------");
                // Update the underlying file.
                w.Flush();
                w.Close();
            }
            return true;
        }
        public bool Write(Exception ex)
        {

            Write(ex.Message);
            return true;
        }
    }

XmlFileLog
class XmlFileLog : ILog
    {
        public bool Write(string message)
        {
            string xmlFilePath = ConfigurationManager.AppSettings["LogTarget"].ToString();
            if (File.Exists(xmlFilePath))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(xmlFilePath);
                XmlDocumentFragment docFrag = doc.CreateDocumentFragment();
                XmlNode nod = doc.SelectSingleNode("Logs");
                docFrag.InnerXml = "" + message + "";
                nod.AppendChild(docFrag);

                doc.Save(xmlFilePath);
                return true;
            }
            else
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;     //設置縮進      
                settings.ConformanceLevel = ConformanceLevel.Auto;
                settings.IndentChars = " ";
                settings.OmitXmlDeclaration = false;
                using (XmlWriter writer = XmlWriter.Create(xmlFilePath, settings))
                {
                    //Start writing the XML document
                    writer.WriteStartDocument(false);
                    //Start with the root element
                    writer.WriteStartElement("Logs");
                    writer.WriteStartElement("Log");
                    writer.WriteStartElement("Time");
                    writer.WriteString(DateTime.Now.ToLocalTime().ToString());
                    writer.WriteEndElement();
                    writer.WriteStartElement("Message");
                    writer.WriteString(message);
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                    //Flush the object and write the XML data to the file
                    writer.Flush();
                    return true;
                }

            }
        }
        public bool Write(Exception ex)
        {
            Write(ex.Message);
            return true;

        }
    }


App.config配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<appSettings>
    
<add key="LogType" value="LogClassLibrary.TextFileLog"/>
    
<!--
    本程序集配置
    
<add key="LogType" value="ConsoleApplication2.Log例子.TextFileLog"/>
    
-->
    
<!-- XmlFileLog  TextFileLog-->
    
<add key="LogTarget" value="c:\log.txt"/>
  
</appSettings>
</configuration>


主程序

public static void Main()
        {
#region 同程序集下
System.Type type=System.Type.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
ILog log = (ILog)Activator.CreateInstance(type);
log.Write(new Exception("異常測試"));
#endregion
        }

如果在不同的程序集下,那主函數和配置會略有不同

不同程序集主函數

 public static void Main()
    {

#region 不同程序集
string assemblyPath =

Path.Combine(Environment.CurrentDirectory, "LogClassLibrary.dll");
Assembly a = Assembly.LoadFrom(assemblyPath);
Type type = a.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
LogClassLibrary.ILog log =

(LogClassLibrary.ILog)type.InvokeMember(null,

BindingFlags.CreateInstance,null,null,null);
log.Write(new Exception("異常測試"));
#endregion

}

這部分源碼下載

源碼下載

2、插件編程技術

插件是指遵循一定的接口規范、可以動態加載和運行的程序模塊。從上面的例子可以看出,通過反射可以非常方便的動態加載程序集。因此,利用反射的動態加載代碼能力,可以很容易的實現插件。插件編程的要點是使用接口來定義插件的功能特征。插件的宿主程序通過接口來確認、裝載和執行插件的功能,實現插件功能的所有類都必須實現定義插件的接口。

這里只是選貼一部分代碼,詳細分析請看源碼

結構圖

接口部分

接口

public interface IHost
    {
        List Plugins { get; }
        int LoadPlugins(string path);
        ILog GetLog(string name);

    }
 public interface ILog
    {
        bool Write(string message);
        bool Write(Exception ex);

    }

 
宿主實現
 

public class Host : IHost
    {
        private List plugins = new List();
        #region IHost 成員

        public List Plugins
        {
            get { return plugins; }
        }

        public int LoadPlugins(string path)
        {
            string[] assemblyFiles = Directory.GetFiles(path, "*.dll");
            foreach (var file in assemblyFiles)
            {
                Assembly assembly = Assembly.LoadFrom(file);
                foreach (var type in assembly.GetExportedTypes())
                {
                    if (type.IsClass && typeof(ILog).IsAssignableFrom(type))
                    {
                        ILog plugin = Activator.CreateInstance(type) as ILog;
                        plugins.Add(plugin);

                    }
                }
            }
            return plugins.Count;
        }

        public ILog GetLog(string name)
        {
            foreach (var item in plugins)
            {
                if (item.GetType().ToString()==name)
                {
                    return item;
                }
               
            }
            return null;
        }

        #endregion
    }


ILog的實現和上例基本一樣,請參考

主程序代碼static void Main(string[] args)
        {
            Host.Host host = new Host.Host();
            host.LoadPlugins(".");
            InterfaceLayer.ILog log = host.GetLog(ConfigurationManager.AppSettings["LogType"].ToString());
            log.Write(new Exception("異常測試"));
        }

插件編程源碼下載

源碼下載

3、分析對象,得到對象中的屬性值

大家使用應都用過asp.net中的DropdownList,在綁定其值的時候絕大多數情況下我們做的都是同樣的事情,獲得數據源,根據數據源中的某些列綁定控件,下邊我們來說說通用情況的處理方式。我們只需要提供數據集合,以及需要綁定到控件的兩個屬性(text,value)名即可。


public class DDlControl
    {
        private ListControl underlyingList;

        public DDlControl(ListControl underlyingList)
        {
            this.underlyingList = underlyingList;
        }

        public void Add(IDDL ddl)
        {
            underlyingList.Items.Add(new ListItem(ddl.Name, ddl.Value));
        }
        public void Add(T t, string nameStr, string valueStr)
        {
            string name = Convert.ToString(t.GetType().InvokeMember
                   (nameStr, System.Reflection.BindingFlags.GetProperty, null, t, null));
            string value = Convert.ToString(t.GetType().InvokeMember
                (valueStr, System.Reflection.BindingFlags.GetProperty, null, t, null));
            Add(new DDLStruct(name,value));
           
        }
        public void Clear()
        {
            underlyingList.Items.Clear();
        }

        public IDDL SelectedItem
        {
            get
            {
                ListItem item = underlyingList.SelectedItem;
                return new DDLStruct(item.Text, item.Value);
            }
        }

        public void BindTo(IEnumerable list, string nameStr, string valueStr)
        {
            Clear();
            foreach (var item in list)
            {
                Add(item, nameStr, valueStr);
            }
        }


        public string SelectValue
        {
            get
            {
                return underlyingList.SelectedValue;
            }
            set
            {
                underlyingList.SelectedValue=value;
            }
        }
    }
public struct DDLStruct
    {
        public DDLStruct(string name, string value)
        {
            this.name = name;
            this.value = value;
        }
        private string name;
        private string value;
        public string Name
        {
            get { return name; }
        }

        public string Value
        {
            get { return value; }
        }
    }

【編輯推薦】

  1. C#連接數據庫和更新數據庫
  2. C#中使用多線程訪問Winform問題解決方案
  3. 淺析C#3.0編碼習慣與命名規則
責任編輯:彭凡 來源: 博客園
相關推薦

2024-03-04 18:49:59

反射C#開發

2011-06-08 10:06:32

C#

2010-02-04 11:23:25

C++反射機制

2009-08-31 09:41:05

C#反射靜態方法開發

2009-09-03 11:00:29

C#反射機制

2011-09-27 10:23:24

Java反射機制

2025-03-06 00:33:09

動態編程C#

2009-08-24 16:19:42

C# 泛型方法

2021-03-15 08:18:23

C#反射模塊

2024-09-18 00:00:02

反射C#元數據

2009-08-28 13:12:56

C#反射實例C#反射

2009-02-20 09:50:29

C#方法重載編程

2011-05-26 15:23:34

JavaReflection

2011-08-29 10:35:53

反射方式C#

2025-04-30 01:50:00

C#異步編程

2011-06-30 10:28:50

C#開發

2009-10-13 09:05:45

反射機制

2009-08-25 17:13:57

C#串口編程

2009-08-12 17:32:44

C#反射方法

2009-01-19 10:26:02

C#Namespace.NET
點贊
收藏

51CTO技術棧公眾號

欧美午夜激情小视频| 国产在线观看第一页| 成人免费一级视频| 国产亚洲欧美日韩在线观看一区二区| 狠狠色2019综合网| 亚洲男子天堂网| 日韩成人三级视频| 国产精品无码白浆高潮| 精品久久美女| 欧美色播在线播放| 在线免费观看一区二区三区| 伊人久久久久久久久久久久| 欧美自拍一区| 亚洲成人精品一区二区| 97se亚洲综合| 国产美女久久久久久| 在线一区视频观看| 国产视频一区在线观看| 欧美综合在线第二页| 久久一区二区电影| 欧美a级在线观看| 成人va在线观看| 欧美激情视频播放| av电影在线播放| 国产探花视频在线观看| 91日韩在线| 91高清在线观看| 青娱乐国产91| 日韩精品一区二区亚洲av观看| 开心激情综合| 精品久久久久久久久久久| 国产91免费视频| 久久精品视频9| 人妖一区二区三区| 欧美一级二级在线观看| 日韩成人午夜影院| 亚洲免费一级片| 青青草精品视频| 久久精品精品电影网| 中文字幕人妻无码系列第三区| 亚洲区欧洲区| 成人av网站在线观看| 国产在线播放不卡| 真实国产乱子伦对白在线| 在线播放一区二区精品视频| 午夜精品久久久久久久| 欧美日韩精品免费观看视一区二区| 日韩在线视频不卡| 天天做天天爱综合| 亚洲国产第一页| 国产自偷自偷免费一区 | 99riav视频在线观看| 26uuu亚洲婷婷狠狠天堂| 国产成人久久久精品一区| 少妇太紧太爽又黄又硬又爽小说| 精品一区91| 欧美日韩免费区域视频在线观看| 色一情一乱一伦一区二区三区丨 | 欧美做爰啪啪xxxⅹ性| 欧美三级三级| 欧美在线制服丝袜| 在线观看三级网站| 性感美女一级片| 蜜臀av一区二区在线观看| 欧美日韩成人网| 一本色道久久综合亚洲精品图片| 亚洲网站三级| 欧美日韩亚洲国产一区| 国产乱子伦农村叉叉叉| 欧美日本高清| 久久女同精品一区二区| 444亚洲人体| 朝桐光av在线一区二区三区| 久久久久国产精品午夜一区| 欧美不卡视频一区发布| 最近中文字幕免费视频| 91精品久久久久久综合五月天 | 91wwwcom在线观看| 黑人と日本人の交わりビデオ| 国产欧美日韩免费观看| 中文字幕精品av| bl动漫在线观看| 久久免费福利| 欧美精品一区二区不卡| 久久综合在线观看| 国产毛片精品久久| 欧美午夜精品伦理| 一级在线免费视频| 女人高潮被爽到呻吟在线观看| 色中色一区二区| 波多野结衣之无限发射| jizz性欧美| 国产精品久久久久影院老司| 蜜桃麻豆91| 色婷婷av一区二区三| 国产久卡久卡久卡久卡视频精品| 国产精品青青在线观看爽香蕉| 欧美一级特黄视频| 国产欧美69| 97在线视频免费观看| 五月婷婷一区二区| 丝袜亚洲精品中文字幕一区| 97视频在线观看视频免费视频 | 久久91视频| 精品国内二区三区| 一级黄色免费毛片| 日韩福利影视| 欧美日韩成人激情| 五月婷婷六月丁香激情| 日韩毛片在线| 欧美mv和日韩mv国产网站| 91成人在线免费视频| 亚洲视频分类| 亚洲精品中文字幕有码专区| 国产精品1000部啪视频| 91精品国产乱码久久久久久久| 日韩中文娱乐网| 可以免费看av的网址| 水蜜桃久久夜色精品一区| 久久久久久999| 日本一区二区网站| 国产欧美一区二区三区国产幕精品| 国产狼人综合免费视频| 国产美女免费看| 国产精品18久久久久久vr| 99国产超薄丝袜足j在线观看| www.天天干.com| 国产精品久久久久影院老司| 国产欧美在线一区| 影音成人av| 精品亚洲va在线va天堂资源站| 青青草免费av| 亚洲精品乱码| 日韩av电影国产| 中文字幕网址在线| 国产盗摄一区二区三区| 一区二区在线不卡| 欧美日韩国产网站| 亚洲人成在线观看网站高清| 99久久99久久精品免费看小说.| 99在线精品免费视频九九视| 国产suv精品一区二区| 婷婷综合激情网| 亚洲综合免费观看高清完整版在线| 91精品国产91久久久久麻豆 主演| 三级在线看中文字幕完整版| 精品乱码亚洲一区二区不卡| 欧美激情图片小说| 美女日韩在线中文字幕| 精品九九九九| 秋霞a级毛片在线看| 在线一区二区三区做爰视频网站| 中日韩精品一区二区三区 | 久久婷婷国产91天堂综合精品| 欧美jizz18| 社区色欧美激情 | 91亚洲精品国偷拍自产在线观看 | 国产精品主播| 九九九九精品九九九九| 久草在现在线| 一区二区三区美女视频| 亚洲一级片免费观看| 欧美日韩hd| 国产成人黄色av| 成年女人的天堂在线| 亚洲午夜久久久| www欧美激情| 四虎国产精品免费观看| 91精品在线一区| 青春有你2免费观看完整版在线播放高清| 国产精品理论片| 亚洲第一区第二区第三区| 欧美永久精品| 国产精品美女免费视频| 免费不卡视频| 精品奇米国产一区二区三区| 日本天堂在线视频| 久久精品在线观看| 成人午夜视频在线观看免费| 美女一区二区在线观看| 国产精品69精品一区二区三区| 在线观看免费黄视频| 一本一道波多野结衣一区二区| 免费看的黄色网| 久久国产成人| 亚洲一区二区三区午夜| 国产精欧美一区二区三区蓝颜男同| 欧美成人一区二区三区在线观看| 日韩欧美在线视频播放| 午夜亚洲影视| 国产精品国产精品国产专区蜜臀ah| 国产在线看片| 欧美精品在线观看一区二区| 免费在线观看a视频| 国产麻豆成人精品| 成人羞羞国产免费网站| 欧美亚视频在线中文字幕免费| 国产不卡视频在线| 成人三级网址| 亚洲天堂开心观看| www香蕉视频| 欧美亚洲日本国产| 高清国产在线观看| 国产91精品精华液一区二区三区 | av资源网站在线观看| 日韩精品自拍偷拍| 中文字幕视频在线播放| 欧美日韩免费在线观看| 亚洲成人生活片| 中文在线一区二区| 九九视频精品在线观看| 国产一区二区三区四区三区四| 91精品国产一区二区三区动漫| 成人免费看视频网站| 欧美黄色片视频| 一区二区三区视频网站 | 日韩av片专区| 四季av一区二区三区免费观看| 国产一区二区自拍| 五月天国产在线| 亚洲色图美腿丝袜| 欧美一区二区三区激情| 精品成人av一区| 欧美特级一级片| 中文字幕不卡在线观看| 97超碰在线资源| gogo大胆日本视频一区| 青青在线视频观看| 久久日文中文字幕乱码| 欧美日韩视频在线一区二区观看视频| 999久久久久久久久6666| 91av视频在线播放| 欧美激情成人动漫| 日韩激情视频在线| 中文字幕免费播放| 一本一道久久a久久精品| 狠狠躁夜夜躁人人爽天天高潮| 国产精品一区二区免费不卡| 99sesese| 蜜臀精品一区二区三区在线观看 | 国产精品久久久久7777| 噜噜噜天天躁狠狠躁夜夜精品| 91夜夜揉人人捏人人添红杏| 日韩护士脚交太爽了| 国产精品久久久久7777婷婷| 免费网站看v片在线a| 中文字幕日韩av电影| 国产尤物视频在线| 一本大道久久加勒比香蕉| 亚洲av永久纯肉无码精品动漫| 婷婷久久综合九色综合伊人色| 精品无码m3u8在线观看| 国产午夜亚洲精品理论片色戒| 亚洲av无码国产精品久久| 久久久久久久久久久久久久久99 | 日韩欧美在线观看视频| yjizz国产| 色婷婷亚洲一区二区三区| 日韩欧美国产另类| 欧美久久久久久蜜桃| 精品国产无码一区二区三区| 欧美videos大乳护士334| 农村少妇久久久久久久| 亚洲高清一区二| 日本天堂在线| 色偷偷偷综合中文字幕;dd| 成人短视频在线观看| 欧美激情久久久久久| 中文字幕乱码在线播放| 国产精品久久91| 99久久这里有精品| 国产精品区一区二区三含羞草| 欧美在线导航| 亚洲精品一区二| 婷婷精品在线| 国产 高清 精品 在线 a| 欧美成人一区在线观看| 日本不卡二区高清三区| 婷婷综合视频| 亚洲色成人www永久在线观看| 欧美一级网站| 福利视频999| 免费欧美日韩国产三级电影| 免费高清视频在线观看| 99麻豆久久久国产精品免费| 国产午夜福利一区| 久久久亚洲精品一区二区三区| 99久久99久久精品免费看小说.| 一区二区三区高清在线| 欧产日产国产69| 4hu四虎永久在线影院成人| 中文字幕一区二区免费| 日韩欧美电影一二三| 男女视频在线观看免费| 日韩激情视频在线播放| 免费在线你懂的| 69国产精品成人在线播放| 日韩综合久久| 久久99精品久久久久久青青日本| 久久国产电影| 亚洲一二三区在线| 亚洲毛片av| 亚洲天堂伊人网| 久久久不卡网国产精品二区 | 亚洲成av人在线观看| 久久精品五月天| 亚洲国产精品成人av| 免费在线你懂的| 国产91露脸中文字幕在线| 999在线精品| 亚洲最新免费视频| 久久综合99| 国产成人久久婷婷精品流白浆| 国产成人精品免费看| 日本成人免费视频| 午夜精品成人在线视频| 国产成人三级在线播放 | 欧美午夜性色大片在线观看| 99在线观看免费| 日日摸夜夜添一区| av在线日韩| 国产精品亚发布| 精品影片在线观看的网站| 日韩精品国内| 五月综合激情| 最近中文字幕一区二区| 久久亚洲精品小早川怜子| 日韩经典在线观看| 欧美精品一区二区三区蜜桃视频| 成人日批视频| 91色精品视频在线| 香蕉国产精品| 国产美女视频免费看| 亚洲欧洲精品成人久久奇米网| 精品国产乱码久久久久久鸭王1| 欧美日韩另类一区| av在线播放网| 国产精品久久久久影院日本| 国产精品免费99久久久| 丰满人妻中伦妇伦精品app| av电影一区二区| 日韩欧美一级视频| 色综合中文网| 亚洲免费看片| 性欧美.com| 蜜桃视频在线观看一区二区| 大又大又粗又硬又爽少妇毛片 | 亚洲啊啊啊啊啊| 国产一区二区不卡| 在线观看中文av| 亚洲美女少妇撒尿| 在线观看国产亚洲| 亚洲美女又黄又爽在线观看| 国偷自产一区二区免费视频| 久久免费看av| 日产国产高清一区二区三区| 免费看的黄色网| 5566中文字幕一区二区电影| 综合久久2o19| 国产精品jvid在线观看蜜臀 | 亚洲AV无码成人精品一区| 精品亚洲国内自在自线福利| 欧美成人黄色网| 亚洲第一免费播放区| 亚洲校园激情春色| 日韩三级电影| 黑人巨大精品欧美一区| 久久久久久久久久久网| 亚洲精品国偷自产在线99热| 毛片免费不卡| 91视频网页| 一本久道久久综合婷婷鲸鱼| 级毛片内射视频| 欧美一区二区免费| 黄色影院在线播放| 国产欧美日韩视频| 欧美日韩一区二区国产| 国产麻豆xxxvideo实拍| 在线亚洲一区二区| 免费av在线播放| 国产伦精品一区二区三区免费视频 | 美女视频一区| 精品一区二区三区无码视频| 91美女在线观看| 国产精品免费无遮挡| 97国产精品视频人人做人人爱| 欧洲激情综合| 亚洲黄色小说在线观看| 综合av第一页| 熟妇人妻av无码一区二区三区| 国产精品久久久久av| 欧美午夜精品| 先锋影音av在线| 精品国产污污免费网站入口| 欧美暴力调教| 999一区二区三区| 国产精品污网站| 无码h黄肉3d动漫在线观看| 成人网址在线观看| 日韩一区自拍|