成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Visual Studio動態(tài)代碼生成的實現(xiàn)基礎(chǔ)

開發(fā) 后端
本文作者之前想談一談如何通過引入框架或代碼生成來解決(在某種程度上)項目開發(fā)實際會遇到的編碼的問題(重復(fù)相似代碼和多種實現(xiàn)問題),順便提醒下初學(xué)者把精力放在靜態(tài)代碼生成器上,還不如放在如何在編輯代碼時動態(tài)生成基礎(chǔ)設(shè)施或持久化的代碼。

 這篇文章討論以下3個問題:

1.代碼生成器應(yīng)該做什么

2.大多數(shù)代碼生成器的缺點

3.動態(tài)代碼生成實現(xiàn)的基礎(chǔ)

代碼生成器應(yīng)該做什么?

我認為,目標(biāo)是加快項目開發(fā),方式是減少重復(fù)代碼手工操作,實現(xiàn)是用過代碼生成技術(shù)。反過來說,就是代碼生成要盡量讓能自動化的代碼不手動來操作。當(dāng)然產(chǎn)生了很多附屬的優(yōu)點,如穩(wěn)定性、便于測試、可以集中精力在業(yè)務(wù)邏輯上等,可是不能本末倒置。套用一句話,一切不以自動化為目的代碼生成器都是耍流氓。

大多數(shù)代碼生成器的缺點

現(xiàn)在大多數(shù)的(應(yīng)該不是所有)代碼生成器有一個***的問題,就是多次生成導(dǎo)致的拷貝粘貼(無法動態(tài)響應(yīng)類結(jié)構(gòu)或表結(jié)構(gòu)的變化)。現(xiàn)在的代碼生成器大多數(shù)是在表結(jié)構(gòu)和類代碼之間單向生成,但不代表代碼生成不能生成其他代碼。就算只從生成持久化代碼的角度考慮,這些代碼生成器除了能根據(jù)某個時間點的狀態(tài)生成一次性的代碼,就沒有什么價值了。而這些生成的代碼如果用于實際項目(不可能不調(diào)整結(jié)構(gòu)),又會進行多次生成,產(chǎn)生多次拷貝粘貼。這樣的代碼生成器其實就是YY,只是YY。當(dāng)然YY有理(我就曾是其中一員),YY無罪。我只想問問有幾個人在項目中實際使用了?有幾個人的項目連表結(jié)構(gòu)和字段都沒改過? 我跟大家一樣都曾經(jīng)對代碼生成器很感興趣,都自己去DIY一個。我甚至在實際項目中嘗試使用,可惜效果并不好。

理想的代碼生成器

理想的代碼生成器在我看來應(yīng)該有以下優(yōu)點:

1.能夠集成到開發(fā)環(huán)境中

2.能夠隨時根據(jù)模型或數(shù)據(jù)表的變化重新生成代碼

3.通過分部類或繼承完全隔離手工代碼出現(xiàn)在生成代碼的文件中

4.不要實體類和數(shù)據(jù)表之間直接映射

動態(tài)代碼生成實現(xiàn)的基礎(chǔ)

如果Visual Studio提供了對2種方式(從代碼或數(shù)據(jù)表開始)代碼生成的支持(如上所述,我不建議直接映射):

1.CodeModelEvents事件提供了對動態(tài)檢測模型變化并重新生成數(shù)據(jù)表的支持。

2.通過AddIn方式、T4方式對數(shù)據(jù)庫表進行動態(tài)檢測并重新生成模型文件的支持。

CodeModelEvents 的示意代碼

  1. /// <summary>實現(xiàn) IDTExtensibility2 接口的 OnConnection 方法。接收正在加載外接程序的通知。</summary> 
  2. /// <param term='application'>宿主應(yīng)用程序的根對象。</param> 
  3. /// <param term='connectMode'>描述外接程序的加載方式。</param> 
  4. /// <param term='addInInst'>表示此外接程序的對象。</param> 
  5. /// <seealso class='IDTExtensibility2' /> 
  6. public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, refArray custom) 
  7. _applicationObject = (DTE2)application; 
  8. _addInInstance = (AddIn)addInInst; 
  9.   
  10. OutputWindow outputWindow = (OutputWindow)_applicationObject.Windows.Item(Constants.vsWindowKindOutput).Object; 
  11. outputWindowPane = outputWindow.OutputWindowPanes.Add("Customer Event Information"); 
  12.   
  13. codeModelEvents = ((Events2)_applicationObject.Events).get_CodeModelEvents(null); 
  14. codeModelEvents.ElementChanged += CodeModelElementChanged; 
  15. codeModelEvents.ElementAdded += CodeModelElementAdded; 
  16. codeModelEvents.ElementDeleted += CodeModelElementDeleted; 
  17.   
  18. /// <summary>實現(xiàn) IDTExtensibility2 接口的 OnDisconnection 方法。接收正在卸載外接程序的通知。</summary> 
  19. /// <param term='disconnectMode'>描述外接程序的卸載方式。</param> 
  20. /// <param term='custom'>特定于宿主應(yīng)用程序的參數(shù)數(shù)組。</param> 
  21. /// <seealso class='IDTExtensibility2' /> 
  22. public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom) 
  23. if(codeModelEvents!=null
  24. codeModelEvents.ElementChanged -= CodeModelElementChanged; 
  25. codeModelEvents.ElementAdded -= CodeModelElementAdded; 
  26. codeModelEvents.ElementDeleted -= CodeModelElementDeleted; 
  27. /// <summary> 
  28. /// 輸出即使窗口信息 
  29. /// </summary> 
  30. /// <param name="Element"></param> 
  31. private void OutPutElementMessage(CodeElement Element) 
  32. outputWindowPane.OutputString("文件:" + Element.ProjectItem.Document.Name + "\n"); 
  33. outputWindowPane.OutputString("元素:" + Element.Name.ToString() + "\n"); 
  34. outputWindowPane.OutputString("類型:" + Element.Kind.ToString() + "\n"); 
  35. /// <summary> 
  36. /// 代碼模型元素更改 
  37. /// </summary> 
  38. /// <param name="Element"></param> 
  39. /// <param name="Change"></param> 
  40. private void CodeModelElementChanged(CodeElement Element, vsCMChangeKind Change) 
  41. OutPutElementMessage(Element); 
  42. /// <summary> 
  43. /// 代碼模型元素更改 
  44. /// </summary> 
  45. /// <param name="Element"></param> 
  46. private void CodeModelElementAdded(CodeElement Element) 
  47. OutPutElementMessage(Element); 
  48. /// <summary> 
  49. /// 代碼模型元素刪除 
  50. /// </summary> 
  51. /// <param name="Parent"></param> 
  52. /// <param name="Element"></param> 
  53. private void CodeModelElementDeleted(object Parent, CodeElement Element) 
  54. OutPutElementMessage(Element); 

運行效果:

可以在AddIn或T4中檢測數(shù)據(jù)庫表結(jié)構(gòu)的變化,示意代碼如下

  1. <#@ template debug="false" hostspecific="True" Language="C#" #> 
  2. <#@ output extension=".cs" #> 
  3. <#@ Assembly Name="EnvDTE" #> 
  4. <#@ Import Namespace="EnvDTE" #> 
  5. <#@ Assembly Name="System.Xml" #> 
  6. <#@ Import Namespace="System.Xml" #> 
  7. <#@ Assembly Name="System.Data" #> 
  8. <#@ Import Namespace="System.Data" #> 
  9. <#@ Import Namespace="System.Data.Common" #> 
  10. <#@ Assembly Name="System.Configuration" #> 
  11. <#@ Import Namespace="System.Configuration" #> 
  12. using System; 
  13. namespace <
  14. DTE dte = ((DTE)((IServiceProvider)this.Host).GetService(typeof(DTE))); 
  15. Project project = null
  16. try 
  17. project = dte.SelectedItems.Item(1).ProjectItem.ContainingProject; 
  18. catch 
  19. project = dte.SelectedItems.Item(1).Project; 
  20. this.Write(project.Name); 
  21. #>.Model 
  22. <
  23. ProjectItem configItem = null
  24. try 
  25. configItem = project.ProjectItems.Item("web.config"); 
  26. catch 
  27. configItem = project.ProjectItems.Item("app.config"); 
  28. XmlDocument configDoc = new XmlDocument(); 
  29. configDoc.Load(configItem.Document.FullName); 
  30. XmlNode node = configDoc.SelectSingleNode("//configuration//connectionStrings//add[@name='ConnectionString']"); 
  31. string providerName = node.Attributes["providerName"].Value; 
  32. string connectionString = node.Attributes["connectionString"].Value; 
  33. DbProviderFactory factory = DbProviderFactories.GetFactory(providerName); 
  34. using (DbConnection conn = factory.CreateConnection()) 
  35. conn.ConnectionString = connectionString
  36. conn.Open(); 
  37. DataTable schema = conn.GetSchema("TABLES"); 
  38. for (int i = 0; i < schema.Rows.Count; i++) 
  39. // 
  40. conn.Close(); 
  41. #> 

 

在AddIn中也可以直接使用CodeModel或FileCodleModel直接進行代碼生成,如果通過T4,可以通過調(diào)用Solution.FindProjectItem找到T4文件,通過Open和Save方法讓T4模板自動運行更新代碼來達到動態(tài)更新的目的。

后記

T4的在我的電腦上實在是慢,每次總要弄的VS卡住一小會,如果在AddIn中直接生成代碼又失去了模板的靈活性,考慮在AddIn中先生成中間映射文件,再通知代碼生成程序來調(diào)用T4的模板方式或其他方式來生成代碼,也許效果會更好些。對于代碼生成,我現(xiàn)在的理解就是應(yīng)該集成到IDE中并可以動態(tài)調(diào)用,做到生成代碼不能改動,重新生成十分方便,將由于結(jié)構(gòu)變化導(dǎo)致需要調(diào)整的代碼部分的工作量壓縮到最小。

每隔一段時間,園子里總會熱一段代碼生成相關(guān)的話題。我希望盡量不誤導(dǎo)初學(xué)者,尤其是那些說自己的代碼生成器生成大部分代碼的,提高了多少倍工作效率的,要么是基本不提需求變化,要么是變化了很少改動結(jié)構(gòu),或者根本是自己寫的穩(wěn)定需求。從我個人實踐的角度,用這些所謂的外置的代碼生成器,一旦數(shù)據(jù)庫表結(jié)構(gòu)生成變化,就需要重新生成代碼并拷貝進項目。本來代碼生成就不是只針對對象持久化方面,也不是只有外置的方式,甚至在我看來外置的方式就是YY。

代碼生成這個東西,生成的應(yīng)該是經(jīng)過實踐的、穩(wěn)定的、可以自動生成的代碼。如果對生成的代碼理解都很困難還在嘗試寫自己的代碼生成器,我覺得不好。寫代碼生成器,如果拋開代碼生成產(chǎn)生的根源和要解決的問題,一再的強調(diào)一些不相關(guān)的東西,卻一直回避到底如何在應(yīng)用中加快項目進度、提高效率等這些內(nèi)容,對初學(xué)者真的是很不好的影響。一個編碼能力很差(這么說不表示我編碼能力強,我就是很弱的那種),閱讀代碼能力都不行的,公布一個代碼生成器,你這是鬧哪出呢。

也許有人說,初學(xué)者可以在自己編寫代碼生成的過程中學(xué)到很多知識,比如界面和控件、模板等,這是另一種方式的自欺欺人。大多外置代碼生成器都不是web方式的,如果工作中一直從事asp.net開發(fā),那所謂的界面和控件學(xué)到的知識還不如去學(xué)學(xué)自定義web控件開發(fā)了,除了代碼生成,學(xué)到的模板知識在其他哪些方面基本沒啥作用。畢竟所有初學(xué)者都遇到這種必須用模板的需求只能是YY。

通過查找發(fā)現(xiàn)相似代碼,進行重構(gòu),引入框架或代碼生成,本身就對代碼能力有一定的要求,一些基礎(chǔ)的代碼實現(xiàn)和代碼結(jié)構(gòu)都搞不懂,就想做個會有很多人使用的某某代碼生成器,既浪費了自己的時間又誤導(dǎo)了初學(xué)者,這樣不好。我就有過這樣的經(jīng)歷,希望能對別人也起到一些警醒的作用,在本身閱讀代碼和寫一些基礎(chǔ)代碼的能力都沒有的時候,別跟風(fēng),別浮躁,努力提高自己的基礎(chǔ),即使研究代碼生成,也從加快項目進度的角度出發(fā),把精力用在集成在IDE中的動態(tài)代碼生成上,要有一種追根溯源,立足實用的態(tài)度,不要看人家把msdn的示例代碼改一改發(fā)個隨筆說成自己原創(chuàng),你就模仿,也不要看別人發(fā)了很多新技術(shù)的掃盲或入門系列很火,你就模仿。更不要看一些人用標(biāo)題忽悠了很多人評論,你也照著做。搞不清楚來龍去脈,不要去學(xué)人家拋什么“XX技術(shù)無用論”,用"最XX的XX"之類的眼球文。即使能獲得很多不明真相的小白的推崇,誤導(dǎo)了眾多停留在索要源代碼為目標(biāo)的初學(xué)者,也不能對自己起到任何提升的作用。

原文鏈接:http://www.cnblogs.com/easygame/archive/2012/09/18/2690819.html

【編輯推薦】

  1. Visual Studio 2012的C++原生單元測試
  2. Visual Studio 2012 Ultimate RC安裝手記
  3. VS 2012單元測試和測試資源管理器
  4. 微軟正式發(fā)布 Visual Studio 2012
  5. Visual Studio 11下的C++異步編程1

 

責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2009-06-16 10:44:50

JS代碼折疊Visual Stud

2010-03-11 16:09:38

Visual StudSilverligh

2011-01-10 08:48:53

2009-11-05 09:42:42

Visual Stud

2009-09-07 09:22:17

Visual Stud代碼片段

2022-04-01 15:16:40

GitHub程序員人工智能

2009-08-21 13:29:20

Visual Stud

2010-09-25 08:50:00

Visual Stud

2009-12-04 11:17:00

Visual Stud

2009-12-10 16:50:58

Visual Stud

2009-12-02 09:43:38

Visual Stud

2009-12-04 14:29:05

Visual Stud

2011-02-18 10:46:57

Visual Stud

2009-07-01 17:30:14

樣式生成器Visual Stud

2023-09-05 07:32:22

vscode開源故障

2013-11-14 01:09:35

微軟Visual StudVisual Stud

2009-12-04 17:21:35

Visual Stud

2009-12-10 17:05:10

Visual Stud

2012-04-25 11:04:13

Visual Stud

2010-03-11 16:29:28

Visual Stud
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 99精品国产一区二区三区 | 欧美美女爱爱视频 | 天堂资源| 国产精品久久久久久久一区二区 | www.9191| 人人做人人澡人人爽欧美 | 午夜小视频在线播放 | 国内av在线 | 国产成人精品av | 久艹av| 日韩成人精品一区二区三区 | 亚洲精品一区二区三区蜜桃久 | 日韩在线观看网站 | 日韩在线欧美 | 欧美伦理一区 | 午夜激情视频 | 精品国模一区二区三区欧美 | 久久久女女女女999久久 | 91亚洲精品在线观看 | 欧美日韩国产不卡 | 91在线第一页 | 久久蜜桃av一区二区天堂 | 亚洲成人免费在线观看 | 国产91在线 | 亚洲 | 日韩视频区| 做a视频 | 免费成人av网站 | 久久国内 | 免费观看一区二区三区毛片 | 国产九九精品视频 | 在线视频日韩 | 国产精品毛片av一区 | 国产成人精品亚洲日本在线观看 | 国产精品永久久久久久久www | 国产精品jizz在线观看老狼 | 国产剧情一区 | 天天草天天 | 国产精品一区二区视频 | 久久亚洲天堂 | 久久香蕉精品视频 | 久久精品91|