zoukankan      html  css  js  c++  java
  • (转)修改的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:......
                       

  • 相关阅读:
    【spring-boot】mybatis-generator 使用入门
    【spring-boot】mybatis 使用入门
    【spring-boot】logback+slf4j 日志组合
    【spring-boot】写一个简单的单元测试
    github执行clone操作时报错
    enable device: BAR 0 [mem 0x00000000-0x003fffff] not claimed
    Meson version is 0.44.1 but project requires >=0.45.
    tig
    Unknown command 'run'
    systemctl enable rc-local.service error
  • 原文地址:https://www.cnblogs.com/fcsh820/p/2636555.html
Copyright © 2011-2022 走看看