(转)修改的T4代码生成器(续)

原文地址:

http://www.cnblogs.com/ASPNET2008/archive/2012/07/29/2612954.html

 

 

 

    最近一段时间,我利用业余时间在做一个基于客户公司风格的代码生成器,这个代码生成器在之前的文章中稍微介绍过(修改的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 { get; set; }
        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:......
                   

posted on 2012-08-13 16:01  黑子范  阅读(303)  评论(1编辑  收藏  举报

导航