多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php框架 > 框架設計 > 使用 .NET WinForm 開發所見即所得的 IDE 開發環境,實現不寫代碼直接生成應用程序

使用 .NET WinForm 開發所見即所得的 IDE 開發環境,實現不寫代碼直接生成應用程序

來源:程序員人生   發布時間:2015-04-24 08:00:06 閱讀次數:5557次

直接切入正題,這是我09年到11年左右業余時間編寫的項目,最初的想法很簡單,做1個能拖拖拽拽就直接生成利用程序的工具,不用寫代碼,把能想到的業務操作全部封裝起來,通過配置的方式把這些業務操作組織起來運行。

項目的核心功能已基本實現,但12年以后我基本停止了這方面的開發,現在翻出來在這里寫出來想和大家交換1下。

 

鑒于篇幅和精力的緣由,請諒解我這篇博文對技術實現的具體細節談的不是很多,只能算是1個概述。對業務的說明也不多,我想大家都是技術流,應當1看就明白。

寫這個項目的時間是56年前,現在回過頭去看,有很多不足的地方,設計上的,技術上的都有,加上當時技術力有限,不足的地方還請指正,謝謝。

后續是不是會寫1個系列的博文詳細的分析講授實現方法,我暫時也沒有想好,主要是沒有太多時間,我現在基本又回到了當初每天只睡45個小時的狀態。

如果此篇博文有點兒價值,給個推薦唄 ^_^ 

 

項目使用了 .Net Framework 3.5 開發,分為兩大塊: IDE 和 運行時(解析器)

IDE中開發的項目在打包后生成 zip 格式的包,解析器通過讀取 zip 包實時解析運行,有點類似中間語言的概念,但我這里生成的 zip 包中主要以 xml 文件為主,通過 xml 文件對項目的 UI,業務,數據結構 進行描寫。

 

到此可以看出,運行時本身其實不1定是 .Net 或 WinForm 的,而是可使用任何平臺或語言實現,只要讀取 zip 文件和 xml 文件并解析便可。

事實上我自己實現的默許運行時也不是 WinForm,而是用了 Silverlight。

 

再簡單說說 IDE 的設計思路,幾個主要的設計目標以下:

 

1.像 Visual Studio 1樣

  有可視化的環境,拖拖拽拽界面就出來了。

2.模塊化設計

  功能模塊全部獨立,解耦,以插件的情勢存在于主程序(宿主)中。

2.不要寫代碼,業務通過界面,向導進行配置

  拖1個按鈕上去,想要單擊時做1件事情,就先把按鈕拖上去,然后設置這個按鈕的事件序列,配置對應的事件。

3.把事件這個概念抽象并封裝起來

  如“保存數據”這個事件,配置好數據的來源,如窗體上的數據,或系統數據,再配置好要保存的目標,某種數據實體,便可,這個事件被添加到某個事件序列,如按鈕的單擊事件序列中,項目被運行時解析時,就會按鈕這個邏輯履行。

4.對數據操作要有1定的自由度

  除基本的向導式配置之外,要能滿足特殊需求,比如支持自定義 sql 語句。但是自定義 sql 語句怎樣與數據源,目標交互呢?我設計了1種簡單的表達方法,如 UPDATE FROM [User] SET [Name] = {FormElement.txtName} WHERE [Id]={System.UserId}

5.數據庫數據表的操作怎樣交互

  就是將其抽象為“數據實體”,數據實體也在 IDE 中由用戶自己定義,定義的進程類似于 SqlServer,定義好數據實體以后,在 IDE 中進行設計時,通過數據實體來抽象對數據庫、表的操作,在打包項目時,可以根據定義的數據實體,生成多種數據庫,如 SqlServer,Mysql 等。

6.資源文件的管理

  在項目中必定要援用到外部資源,這部份外部資源,怎樣引入,管理,打包呢?我在 IDE 中設計了獨立的資源管理器,在 IDE 中設計 UI 時,通過資源管理器援用資源,打包時,將資源打包到 zip 文件中。

7.打包前的靜態編譯檢查

  類似于我們在 Visual Studio 中寫程序,編譯時如果有毛病就會出現正告或毛病提示。在這個 IDE 中,也必須有一樣的功能。當援用的數據實體被刪除,數據項不存在,援用的資源文件不存在,和事件配置中1些問題出現時,能夠實時,并在打包項目時指出這些毛病的具體位置。

8.支持嵌入腳本

  能夠在事件序列中添加自定義腳本,支持在運行時動態解析或調用某種腳本語言。此功能有所設計,但并未開發

9.支持插件

  此處插件支持指的是 IDE 層面能夠支持插件,類似 Visaul Studio 或 Eclipse 的插件機制,我當時使用的是 .NET 管線技術(很冷門),實現了相干DEMO,但是沒有集成到IDE中。

10.IDE界面支持多國語言

  目前IDE完全支持多國語言,所有文本均使用了資源,但是我沒有直接使用資源文件,而是將其強類型化了,具體實現方式下文詳述。

 

在設計開發這個 IDE 的初期,我并沒有給自己設定如此詳細的目標,現在寫其實更多的是回顧和總結。

 

在這個項目中,大量使用了 GDI+ 繪圖,說復雜,給你調用的接口也就那末多,說簡單,用 GDI+ 自己寫1個功能完備的 WinForm 控件,分分鐘教你重新做人。在這個項目中,幾近所有的界面元素都是我自己用 GDI+ 繪制的,使用的第3方控件不多。后面我會寫1些這方面的感想。

 

下面羅列1些技術難點和主要功能點,有些細節可能沒有試著做過都不會心識到那是個問題。

 

1.工具欄按鈕/右鍵菜單的狀態控制

  就是控制狀態欄上按鈕可用不可用,可見不可見,絕大多數時候這不是個問題,但是作為1個 IDE,工具欄上的各種按鈕非常多,且按鈕的狀態和當前設計器中的選中元素個數,選中元素類型,乃至選中元素本身的狀態等等相干,還有些按鈕是特定控件或元素提供的,怎樣統1控制這些按鈕的狀態?

黃色背景部份是動態掛載上去的,狀態的控制在后文中說明。

 

此處右鍵菜單指的是窗體設計器中的右鍵菜單,在窗體設計器中,右鍵菜單比較復雜,不同控件的右鍵菜單有所不同,有共通的項目,有特殊的項目,和狀態是否是灰掉可能和控件本身的某些因素有關,但右鍵菜單本身是不可能通過處于設計狀態的控件本身提供的,所以此處如何把控件獨有的菜單項掛載上去,又怎樣控制它們的狀態?注意設計器本身和用來設計的控件是解耦合的。

注意這個例子,右鍵 DataGrid 產生的右鍵菜單中存在“添加列” 和“編輯列”兩個特殊的項目。

此處當我選中 DataGrid 時,屬性網格下方也會出現這兩個項目,這里先提1個關鍵概念,叫做“謂詞”,這是1個 DesignSurface 中的概念,后文再詳述。

 

此處實際上我實現了1個獨立的菜單(包括工具欄項目)的管理器,并不是直接創建 MenuItem 之類的實例去使用,這個管理器也是獨立于業務進行設計的,對菜單項的各種狀態,行動都進行了抽象與封裝。在管理器層面統1調度這些菜單項,通過1定的機制使菜單項的狀態與業務狀態關聯起來,不允許外部代碼直接修改菜單項的狀態,整套機制本身,與菜單項在UI層面的實現也是無關解耦的,終究生成可見菜單項時,才會生成特定的控件,如 MenuItem,也能夠換成其它任何菜單項控件,不影響管理器的功能與邏輯。

我記得當時我研究了幾個IDE的設計細節,包括  Visual Studio,應當都采取了類似的機制,好吧我承認是我研究以后鑒戒了它們的機制。

這個問題我放在首位,是我意想到這個問題在大型軟件中,真的是個很大的問題,我現在參與開發的1款電氣化CAD軟件中,就存在這個問題,但是他們初期并未意想到這個問題,也談不上能很好的解決,幾千個菜單項,工具欄按鈕項,直接硬編碼,對他們的狀態控制也談不上成體系,就是粗魯的硬編碼,現在的保護,修改,調劑都異常痛苦。

 

2.窗體設計器

  最初我是自己用 GDI+ 寫了1個簡單的設計器模型,支持拖拽,繪制,動態對齊等等功能,但是越往后越復雜,比如繪制1個 DataGrid,你不能光是1個框框,你要自己去繪制它的列,列頭,如果要繪制1個圖片框,你就要自己去繪制它的圖片內容,要斟酌圖片的縮放方式等等細節,如果要1條道走到黑完全自己實現,本錢將非常高昂。

先看看初期直接使用 GDI+ 實現的效果:

 

下面是直接使用微軟 DesignSurface 效果:

和 Visual Studio 效果1樣,不過這里需要注意的是 DesignSurface 僅僅也只是提供了基本的窗體設計能力(圖中右邊部份),比我上面GDI+自己寫的功能多不了多少,但是不用自己繪制控件的外觀,其它輔助功能都是需要自行開發的。

這里要注意的1點是窗體設計器中 允許被設計 的控件 們,是與設計器本身,與IDE解耦的,是完全獨立實現的,后期添加新控件,修改控件都與IDE無關,這個地方的難點決然是解耦合,各種解耦合。

左邊的屬性列表是自行開發的,.Net Framework 中確切提供了 PropertyGrid 控件,但是對高階開發此處其實不適用,有很多制限,下文詳述。

 

 

3.工具箱

  工具箱本身是獨立實現的,不依賴其所處的窗體設計器,同時它本身所承載的控件,也是動態載入的,后期允許第3方插件掛載控件到工具箱中。

  這個地方需要注意的不多,1個是動態載入控件,另外一個就是在和窗體設計器交互的時候,比如我拖1個控件到設計器上,這里是需要對接 DesignSurface 的。

 

4.屬性網格(PropertyGrid)

.Net Framework 中提供了 PropertyGrid 控件,可以實現對對象實例的屬性編輯功能,但是難于擴大與自定義,我此處需要個性化定制的地方比較多,所以選擇自己實現1個。

主要實現了以下功能

1)對單個對象實例,列出它的屬性(Property,下同),和屬性的值,如果屬性值與默許值不同,能夠粗體顯示。

2)對特殊的屬性,提供對應的擴大編輯器,如色彩屬性,在點擊后應當提供1個色彩選擇器。且這些擴大編輯器,是與屬性網格本身解偶的。

3)如果同時設置了多個不同類型(Type)的對象實例,例如在窗體設計器中框選了多個控件,這個場景就復雜1些了;首先得到這些對象實例的類型(Type),抽取共通的屬性,屬性網格中僅顯示共通屬性,對某個屬性的值,如果所有對象實例的值是相同的,則顯示,如果有所不同,則留空不顯示。在設置了某個屬性的值以后,能夠將新值設置到這些對象實例中。

 

 

5.撤消重做引擎

這里可以用的上“引擎”2字,由于確切比較復雜,我們先將這個問題簡化,可以簡單理解為對“對象”屬性變化的跟蹤,可以撤消這些變化,也能夠重做這些變化,可以任意步驟的操作。

觸及到的問題和知識點很多,在 IDE 里對象狀態的變化又被抽象為具體的“操作”,和這些操作又要和設計器進行聯動,有1定難度。

UI上的效果是直接使用 GDI+ 自定義的1個列表,其實不是很復雜,其它能夠直觀看的界面UI不多,主要是代碼了。

 

6.事件及事件編輯器

上文中提到,要將經常使用的操作(事件)都封裝起來,通過配置的方式來運行,大方向好像其實不復雜,但是,怎樣做呢?首先事件本身的抽象要獨立,要與窗體設計解耦合,其次“事件”的定義應當允許由第3方插件擴大,乃至“觸發時機”也應當允許由第3方插件進行擴大。以1個最簡單的按鈕為例:

看上去和普通編程中的事件機制沒甚么區分,是的,我們要做的是對其基本機制進行抽象化。例如:

1)觸發時機應當與事件寄主解耦,乃至允許第3方插件掛載觸發時機。

2)事件序列應當與觸發時機解耦,事件序列中的事件定義,應當與以上機制解耦,乃至允許第3方插件擴大。

 

看看項目中實現的效果:

我們就以“為窗體元素加載數據”這個事件為例,看看現在的事件編輯器大概是甚么樣子。

這個事件支持“關聯數據實體方式”和“履行 SQL 方式”。

切換到數據實體界面中,選1個數據實體,然后設置相干的數據項。

這里就能夠配置事件在履行時,從哪里獲得數據,我們指定了從 用戶 這個數據實體當選擇數據,同時指定了1個條件,就是 用戶的 Id 要等于 指定文本框中的值。

除使用界面元素中的值作為條件,還可使用系統數據,如:

 

對選擇特定的用戶,比如這個 Id 怎樣獲得呢?只要在加載數據時,把 Id 綁定到1個隱藏的文本框中就能夠了,加載數據時,可以讀取它的值。

然后切換到載入界面

在載入界面中,指定我的數據取出來以后,加載到界面的哪些元素中。

我們上文提到,希望對數據的操作有1定的自由度,那末在事件編輯器中,就允許直接定義 sql 語句,或說 sql 語句的模板。

切換到 sql 界面后,首先可以通過 獲得 sql 按鈕自動根據前面的配置生成 sql,然后在此基礎上進行調劑,修改。

在 sql 編輯器中,可以通過 {Provider.Source} 的方式訪問數據。

支持語法著色,支持智能提示。

目前實現了兩種 Provider,FormElement (窗體元素)和 System (系統),在智能提示中支持遞進的提示。

所謂遞進的提示是輸入“{”以后自動給出 Provider,選擇落后1步自動給出 Source 列表。

也能夠在 “{Provider” 后輸入“.” 則自動給出 Source 列表。

智能提示用起來簡單方便,看起來也很簡單,貌似只是1個 Popup ,實則是1個不小的坑,這個功能困惑了我很久,記得當時到處找大神請教,除高談闊論的就是直接告知我不知道,有個人也研究過 SharpDeveloper,告知我這個問題深了,后來我又去翻 SharpDeveloper 的源代碼,參考了它的實現,完成以后還是相當有成績感的。

 

對事件序列的編輯,有兩種方法,1種是在設計器中雙擊控件以后打開的事件序列編輯器

另外一種方法是在窗體設計器中提供了以樹形方式展現的事件序列,可以直接拖動改變事件的觸發時機,或其在事件序列中的位置。

 

事件在解析器中履行時,是按鈕它所處事件序列中的順序進行履行的。

 

目前實現的事件大概有10幾個,基本的利用程序操作,數據交互等。

不再逐一詳細說明,由于事件本事是在解耦的情況下獨立實現的,IDE其實不依賴他們,所以未來擴大也很容易,可以說IDE和解析器是核心引擎,而這些事件定義,只是系統中的“業務”部份。

 

7.集合編輯器

集合編輯器,就真的只是用來編輯對象集合的,支持對集合中對象實例的編輯,和集合中元素順序的調劑,并且在與窗體設計器解耦合的基礎上,與窗體設計器聯動,能夠從窗體設計器中的元素獲得對象集合,同時與撤消/重做引擎對接,在編輯的進程中,提供撤消/重做的支持。

這個編輯器完成以后復用性比較強,在窗體設計器中有很多地方需要對集合進行編輯,行定義,列定義,元素定義之類。

1個典型的使用處景是在窗體設計器中,對 DataGrid 的列進行編輯。

 

8.有效性檢查

在窗體設計器中,能夠對當前窗體中的各項設置,包括的事件進行有效性的檢查。例如我在某個事件中設置了加載數據到 TextBox1 ,后來我刪除這個 TextBox1 ,那末就必須給出提示。

此處的主要難點應當在于解耦合,各種解耦合。

 

9.IDE多國語言實現

  Visual Studio 自帶的資源文件編輯器使用起來不是很方便,比如多國語言,是分開在多個資源文件編輯器窗口中編輯的,沒有逐一對應的顯示語言文本,另外直接使用資源文件,使用的是通過 String 做參數的弱類型方式進行調用的,不能做靜態編譯時檢查,也沒法保證多語言相干編碼的質量。所以這里我沒有直接使用資源文件機制,而是進行了2次開發,我專門開發1個資源文件編輯器,提供1個1體化的界面同時編輯多國語言資源文件,使資源key同時和多個資源文件對應起來,同時支持導出excel,交給翻譯翻譯以后直接導回來,然后解析資源文件中的資源,生成1個統1的 ILanguage 接口,和不同的語言實現,如 class Chinese:ILanguage,class English:ILanguage,調用時,直接使用接口進行強類型調用,行將 Resource.GetString("buttonText") 變換為 _language.buttonText。

  另外一方面,實現了1種將界面文本綁定到資源的機制,這1點在 WPF 下非常方便,在 WinForm 下就要自己動手了。通過特定字符串標記資源key,在運行時自動掃描窗體或其它容器控件,通過解析這些字符串自動查找對應的資源,將其替換。

 

10.界面用戶數據的驗證

  目前幾近所有的開發平臺都提供了比較友好的用戶輸入驗證方案,在 WinForm 下也有,不過其實不是很完善,使用起來限制比較多,功能也有限,不是很順手。

  我自己開發了1套用于 WinForm 的用戶界面數據驗證功能。舉個最簡單的例子,我給文本框設置1個不允許空的屬性,或設置1個正則表達式,在我調用驗證方法時,就可以夠對它進行有效性驗證。方案非常簡單,只是要花點心思把它實現好,各種控件都要支持,要解耦合,驗證器要支持多種不同驗證機制,驗證結果如何向用戶反饋等等。

  這套驗證機制也一樣實現在了運行時(解析器)當中。

驗證結果的反饋其實不1定要用 MessageBox,可以很容易的改進為其它更友好的情勢。

 

11.模塊化設計

模塊化,插件式的框架設計現在應當有很多現成的框架和設計方法,但是在當時,又是 WinForm 下,可以參考的資料非常少,大方向不復雜,但是做完善做細致,在當時對我來講有相當大的難度。當時唯1可以參考的是微軟的 CAB 框架,但在當時來看,CAB 就已是1個有些過時的框架了,使用起來有1些缺點和限制。

我在參考 CAB 的基礎上在 WinForm 下實現了1套分解的非常細致的模塊化開發框架,對軟件的功能進行層層解耦,宿主程序與功能模塊完全無關,而在我業務功能的設計上,IDE中的功能也實現了完全解耦,上文也多處提到了,窗體設計器與被設計的控件包解耦,事件機制與具體的事件定義解耦等等。

 

 

 

其它功能點

其它功能點主要是指:數據實體定義,主菜單定義,枚舉定義,資源管理,和其它小功能等,下文先做個簡單展現,暫不再做詳細的說明。

 

1.歡迎界面

歡迎界面是內嵌了1個 HTML 頁面,只是和 C# 代碼有簡單交互,例如單擊鏈接會調用 C# 方法,并傳入參數。

使用 HTML 的1個緣由是希望歡迎界面比較漂亮,但是在 WinForm 下實現1個漂亮的,交互性強,保護性強的歡迎界面有1定難度,很浪費時間。

此處注意1個細節, URL 地址不是1個磁盤文件地址,而是1個自定義協議和路徑的地址,這個需要自己實現,但是很簡單。

年代久遠,CSS 和圖片可能遺失了,不太好看,見諒。

 

2.數據實體定義

這塊相對照較簡單,沒有復雜功能。

發布項目時可以根據數據實體定義自動生成數據庫

 

也能夠針對指定的數據實體生成腳本。

 

3.枚舉定義

界面很簡單,生成數據庫時,根據枚舉定義向枚舉表插入枚舉數據。

但是有1個小細節是它和窗體設計器是有對接的,它是1個數據源的 Provider,可以在設計器中把控件中的值綁定到枚舉。

 

4.主菜單/工具欄定義

定義要生成的軟件的主菜單和工具欄,運行時解析以后,根據自己的實現方式生成,可以是 Ribbon 的,也能夠是傳統的,或其它方式。

菜單或工具欄項目支持事件,可以掛載事件序列。

 

5.資源管理

實現1個資源管理器,目前只實現了對圖片資源的管理。

 

 

這里有點看點的是,我當時沒有找到我覺得不錯縮略圖控件,因而只好自己實現1個。和 Windows 資源管理器功能1致,沒有需要特殊說明的地方,只是自己從頭實現1個不能說很難,但是真的很麻煩。借這個地方簡單講1下這個縮略閱讀器的實現,可能有些朋友對 GDI+ 不是很了解。

對在 WinForm 下使用 GDI+ 繪制界面(自己實現1個控件),是比較原始的,想像1下給你1張白紙,和1些簡單的繪圖接口,畫線,畫圓,畫矩形,其實沒別的了。畫1個圓角矩形?自己計算坐標系,通過畫弧線和畫直線畫1個。顯示1些文本?自己進行字體字號丈量坐標系換算,如果觸及到文本換行,超長用省略號代替,都是比較麻煩的。

你要自己在 邏輯上 掌控控件的不同狀態,如選中,非選中,鼠標滑過等等,和WPF下預定義的狀態組不同,WinForm 下這些狀態是你要自己去掌控的,狀態切換時,你要自己根據狀態進行重繪……

在繪制界面時,你只有1個從0,0開始的2維的平面坐標系,和它的尺寸。實現這樣1個縮略圖閱讀器,縮略圖的排版,布局,1行顯示多少個,甚么時候換行,選中非選中,鼠標框選,轉動條轉動都需要自己實現,包括鼠標框選時的框,也是需要自己用 GDI+ 繪制的,然后自己計算坐標系,判斷哪些項目應當處于被選中狀態。

這個控件的代碼接近3000行。現在回過頭去看,只覺得注釋不夠詳細。

軟件中大部份自己實現的控件,都采取了類似的架構進行設計:控件本身,布局管理器,顯現器,顯現器實現,主題。

 

6.生成數據庫,生成項目

這里目前其實不復雜,生成數據庫根據數據實體定義生成便可,生成項目目前我直接使用了項目文件,由于我目前的項目文件格式就是 zip 包,內含 xml 文件。

附帶產出是實現了1個簡單的比較通用的向導功能。

 

7.其它控件的美化。

從上面的截圖中能夠看到我使用了相當多的自定義控件,或經過美化的 WinForm 自帶控件,典型的幾個除上面的縮略圖控件,還有IDE上面的主菜單(效果參考了 Paint.NET), DataGrid,重新實現的 ComboBox 等等,竟然1步1步構成了1個自己的控件包。惋惜技術更新換代日新月異,現在也基本用不上了。

 

IDE 部份現在回過頭去看,貌似實際功能其實不多,但是核心架構已基本完全了,后續如果繼續開發,基本相當于開發插件和添加新的功能包。 

其中絕大部份是從空白 class 硬寫出來的,很多地方用現在的眼光去看,存在很大的過度設計問題。

 

解析器部份我是用 Silverlight 實現了1個,核心實現了,業務沒有實現完全,多是我現在的機器 Silverlight 版本有問題還是怎樣回事沒有運行起來,也不想去調試了,

其實不復雜,只是解析 zip 包,xml文件,生成界面,事件處發時解析事件序列中的事件便可。

 

最后,如果你現在要做客戶端軟件,選擇 WPF 吧,生產性非常高,功能非常完善與強大,如果你擔心性能問題,我想說現在已2015年了,不是2005年,如果你在開發中遇到了性能問題或其它問題,先從本身找緣由。

專業程序員永久從本身找問題,業余程序員從平臺從語言找問題。

 

后記:

最后想寫1點點個人的感想與反思。我在開發這個軟件的進程中,犯了許多的毛病,這些毛病未必是技術上的,但都是嚴重毛病。

首當其沖:閉門造車。活在自己的技術宅世界里,歷來不去想,也不愿意去想這個東西有多少實際價值,誰會去用它,到了后來,我明明潛意識里知道這個軟件沒有太大市場價值,就是不愿意去想這個問題,1門心思去開發。我記得那兩年我隨身帶的手機里,記滿了關于這個軟件的想法和1些問題的實現思路。我在路上想到某個解決方案或有甚么想法,就立馬取出手機記錄,怕回去就會忘記。有1個冬季住的地方沒有空調,非常冷,寫代碼1直寫1直寫,兩個手凍青了,就自己用熱水瓶子捂捂繼續寫,那段時間每到周末就特別高興,由于有2個完全的工作日可以利用了,不用單純靠晚上的時間去寫,很長1段時間我每天晚上我都只能睡45個小時,個別時候還沒睡著,天就蒙蒙亮了。但是這么辛苦的意義是甚么呢?我當時沒有認真的思考。

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生

------分隔線----------------------------
分享到:
------分隔線----------------------------
為碼而活
積分:4237
15粉絲
7關注
欄目熱點
關閉
程序員人生
主站蜘蛛池模板: 国产精品久久久久久一区二区三区 | 变态 另类 国产 亚洲 | 91福利一区二区三区 | 天天做夜夜做久久做狠狠 | 日韩理论片在线看免费观看 | 91色久| 久久婷婷人人澡人人爱91 | 精品成人网 | 日本欧美做爰全免费的视频 | 波多野结衣一二三区 | 高清在线观看视频 | 午夜三级三级三点在线 | 77777亚洲午夜久久多人 | 国产jizz美国jizz免费看 | 美女网站在线观看 | 国产aaa免费视频国产 | 热久久视久久精品18国产 | 一二三四视频社区5在线高清视频 | 亚洲一区二区三区视频 | 最新99国产成人精品视频免费 | 91精品一区二区三区在线 | 国产美女久久久久久久久久久 | 欧美高清免费精品国产自 | 日韩精品视频一区二区三区 | 97久久影院 | 国产毛片毛片精品天天看 | 国产精品免费大片一区二区 | 国产欧美视频一区二区三区 | 性欧美videos另类视频 | 亚洲成av人片在线观看无码 | 欧美一级毛片无遮 | 国产成人永久免费视频 | 中文字幕日韩一区二区不卡 | 最新国产网站 | 国产欧美日韩高清专区手机版 | 日本337p| 国内精品视频免费观看 | 亚洲影院在线 | 国产欧美曰韩一区二区三区 | 日本一区二区三区欧美在线观看 | xxx护士|