修改的T4代碼生成器(續)


    最近一段時間,我利用業余時間在做一個基於客戶公司風格的代碼生成器,這個代碼生成器在之前的文章中稍微介紹過(修改的T4代碼生成器),我並不是白手起家,而是參考了一們園友的作品。原作品的特點:


    1:基於WPF。
    比起傳統的WinForm來講,wpf在用戶體驗性上有很大的優勢。
    優點一:能夠比較容易的實現基於Visual風格的界面。
        這讓使用者會比較熟悉,不會花太多時間去了解如何使用。


                                

    優點二:自由拖拽UI元素
       比如我們非常容易的能夠將一個頁面分割成不同的小塊,然后我們可以自由的拖拽這些小塊到不同的區域。

                            
   


     2:基於T4 text template


     其實t4 text template很早以前就出來了,但關注度一直不太高(個人認為)。只不過后來由於微軟的asp.net mvc自身采用了t4,算是一個非常成功的案例,而我們在選擇方案時,往往其中一個比較重要的參考指標就是有沒有成功案例。即然有了微軟的親自實踐,足以說明t4的實用性。


     其實我對於工具的選擇,一直保持比較中立的態度,有些開發人員往往抱怨現成的工具不好用,不能滿足自己的需求,一旦現有的功能實現不了,就說軟件不好用。在微軟沒在asp.net mvc上使用t4前,它的熱度一直不高。一旦有人成功的將某種技術在某個項目上成功的應用開來,大家才發現原來此項技術還是不錯的,只是我們自己不知道如何更好的利用它而已。有些時候,我們需要有能力去在別人的基礎上完善功能,以實現自己的需求,而它的前提就是我們需要得到一個開源項目,否則你需要從0開始。
   

    3:它是開源的。
    只有項目開源,我才有可能不從0開始繼續我自己的代碼生成器,畢竟一個人從0開始做一件事的難度太大,而且我也不可能有那么多時間從頭開始,更重要的是人無完人,如果有其它的作品已經完成了你原來不太熟悉的功能,豈不是很爽。
    
    好了,講了這么多,我再來分享下,我在原作品基礎上的一種改動及應用t4 templeate時遇到過的一些問題。
   
   缺陷:內存漏泄。
   在進行t4生成代碼時,我們可以定義自己的TextTemplatingEngineHost,里面有這樣一個方法

        private  string DomainName =  " Generation App Domain ";
         public AppDomain ProvideTemplatingAppDomain( string content)
        {
             // return AppDomain.CurrentDomain;
            CurrentDomain= AppDomain.CreateDomain(DomainName);
             return CurrentDomain;
        }


    
    它是ITextTemplatingEngineHost接口中的一個方法,在微軟提供的示例代碼中在返回AppDomain時也是新創建的,在代碼中有一段注釋的內容,返回當前AppDomain,但發現運行中有些問題,不知道大家的代碼是如何處理這個方法的。
       
    在使用時我們會先new一個Host:TextTemplatingEngineHost host = new TextTemplatingEngineHost(),問題就在於,每new一個Host都會創建一個AppDomail,最后發現每調用一次,內存就會增加(1到3M內存,有一次多執行幾次批處理,內存就上了600M了),最后我就嘗試手動卸載這些新創建的AppDomail,最后問題解決,為了調用方便,我讓TextTemplatingEngineHost實現IDisposable

        public AppDomain CurrentDomain {  getset; }
         public  void Dispose()
        {
             if ( null != CurrentDomain)
            {
                 try
                {
                    AppDomain.Unload(CurrentDomain);
                    
                }
                 catch (Exception ex)
                {
                     throw  new Exception( " AppDomainUnLoad ERROR! " + ex.ToString());
                }
                 finally
                {
                    CurrentDomain =  null;
 
                }
            }
        }

     
     然后這樣調用:using (TextTemplatingEngineHost host = new TextTemplatingEngineHost()){......}
     
    增強:自動生成edmx。


      由於我們公司項目風格問題,我們數據庫訪問方面采用的是Linq to Entity中的 DataBase First,即先設計好數據庫,然后在UI中添加edmx。所以我們的問題就是如何生成edmx文件,當時的問題:
      問題一:edmx中有很復雜的關系,我們如果用t4模板來實現,有一定難度。
      問題二:每個entity它在UI界面上都有位置關系,及X軸與Y軸數值,這些數值決定了它們在界面上的布局,這些數值是不太好解決的。
     
      解決方案:EdmGen2.exe,這是在EdmGun基礎了封裝出來的,能夠直接生成edmx文件,EdmGen不能直接生成edmx,它只能生成一些源數據文件,比如:csdl,ssdl,msl等。
     
      edmgen2.exe問題:本想直接在程度中調用,但發現傳遞參數時有些問題,在命令窗口中輸入參數時,一般我們用引號將參數包括起來,這樣可以讓程序認為是一個完整的參數,之所以這樣講,是因為大多數的exe的參數是一個string[],它會將輸入的參數以空格分隔成數組,如果我們的參數中包含了空格,就需要用引號包括起來。這種方法直接在命令提示窗口中是沒有問題的,但我們現在是要在應用程序中調用exe,並傳遞參數給它,下面的是錯誤的格式:
     用轉義字符:

string argus =  " /ModelGen  " +  " \" " + SqlConnectionString +  " \"  " +  " \" " +  " System.Data.SqlClient " +  " \"  " +  " \" " + NameSpace +  " \" ";


      
      解決方案:即使edmGen2也是一個開源項目,而且是.net寫的,所以何不直接調用它的方法呢,從而先避免這種參數傳遞。
      第一:將edmgen2的代碼添加到工程中。
      第二:由於edmgen2是一個exe,所以我們需要將默認的Main方法名稱修改成RunMain,將它識別成一個Helper,而不是一個啟動對象。
      第三:直接傳遞string[],而不在傳遞string類型的參數。
 

            string[] argsList= new  string[]{ " /ModelGen ",
            SqlConnectionString,
             " System.Data.SqlClient ",
            NameSpace
            };
            EdmGen2.RunMain(argsList);

     
      
    問題:t4 text template轉義字符  "\" 。


     比如下面的代碼:

<ProjectReference Include= " ..\BusinessLogic\<#=NameSpace.Value#>.BusinessLogic.csproj ">


     這樣寫,<#=NameSpace.Value#>不會被識別成正確的語法,后來發現寫成這樣是沒問題的:即在<#前面多加一個空格。
     

<ProjectReference Include= " ..\BusinessLogic\ <#=NameSpace.Value#>.BusinessLogic.csproj ">

 
     問題:雖然此時t4識別了變量,但我們需要做特殊的處理,即在t4生成文本后,我們需要將這些加的空格刪除,因為在一個正常的路徑中多了一個空格是肯定錯誤的。
     
     解決方案:t4 中轉義字符"\",這樣我樣可以這樣寫:我們不必在刪除空格的問題。
  

<ProjectReference Include= " ..\BusinessLogic\\<#=NameSpace.Value#>.BusinessLogic.csproj ">

    
      這篇比較長了,下篇再寫一些余下的內容:
      1:如何生成Project
      2:如何生成Sln
      3:如何將生成的cs文件引用自動引用動工程中
      4:......
                   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM