(转)修改的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,里面有这样一个方法
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 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,并传递参数给它,下面的是错误的格式:
用转义字符:
解决方案:即使edmGen2也是一个开源项目,而且是.net写的,所以何不直接调用它的方法呢,从而先避免这种参数传递。
第一:将edmgen2的代码添加到工程中。
第二:由于edmgen2是一个exe,所以我们需要将默认的Main方法名称修改成RunMain,将它识别成一个Helper,而不是一个启动对象。
第三:直接传递string[],而不在传递string类型的参数。
SqlConnectionString,
"System.Data.SqlClient",
NameSpace
};
EdmGen2.RunMain(argsList);
问题:t4 text template转义字符 "\" 。
比如下面的代码:
这样写,<#=NameSpace.Value#>不会被识别成正确的语法,后来发现写成这样是没问题的:即在<#前面多加一个空格。
问题:虽然此时t4识别了变量,但我们需要做特殊的处理,即在t4生成文本后,我们需要将这些加的空格删除,因为在一个正常的路径中多了一个空格是肯定错误的。
解决方案:t4 中转义字符"\",这样我样可以这样写:我们不必在删除空格的问题。
这篇比较长了,下篇再写一些余下的内容:
1:如何生成Project
2:如何生成Sln
3:如何将生成的cs文件引用自动引用动工程中
4:......