浅谈Visual Studio动态代码生成的实现基础
2012-09-18 21:09
267 查看
可以在AddIn或T4中检测数据库表结构的变化,示意代码如下:
Code Snippet
<#@ template debug="false" hostspecific="True" Language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="EnvDTE" #>
<#@ Import Namespace="EnvDTE" #>
<#@ Assembly Name="System.Xml" #>
<#@ Import Namespace="System.Xml" #>
<#@ Assembly Name="System.Data" #>
<#@ Import Namespace="System.Data" #>
<#@ Import Namespace="System.Data.Common" #>
<#@ Assembly Name="System.Configuration" #>
<#@ Import Namespace="System.Configuration" #>
using System;
namespace <#
DTE dte = ((DTE)((IServiceProvider)this.Host).GetService(typeof(DTE)));
Project project = null;
try
{
project = dte.SelectedItems.Item(1).ProjectItem.ContainingProject;
}
catch
{
project = dte.SelectedItems.Item(1).Project;
}
this.Write(project.Name);
#>.Model
{
<#
ProjectItem configItem = null;
try
{
configItem = project.ProjectItems.Item("web.config");
}
catch
{
configItem = project.ProjectItems.Item("app.config");
}
XmlDocument configDoc = new XmlDocument();
configDoc.Load(configItem.Document.FullName);
XmlNode node = configDoc.SelectSingleNode("//configuration//connectionStrings//add[@name='ConnectionString']");
string providerName = node.Attributes["providerName"].Value;
string connectionString = node.Attributes["connectionString"].Value;
DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
using (DbConnection conn = factory.CreateConnection())
{
conn.ConnectionString = connectionString;
conn.Open();
DataTable schema = conn.GetSchema("TABLES");
for (int i = 0; i < schema.Rows.Count; i++)
{
//
}
conn.Close();
}
#>
}
在AddIn中也可以直接使用CodeModel或FileCodleModel直接进行代码生成,如果通过T4,可以通过调用Solution.FindProjectItem找到T4文件,通过Open和Save方法让T4模板自动运行更新代码来达到动态更新的目的。
每隔一段时间,园子里总会热一段代码生成相关的话题。我希望尽量不误导初学者,尤其是那些说自己的代码生成器生成大部分代码的,提高了多少倍工作效率的,要么是基本不提需求变化,要么是变化了很少改动结构,或者根本是自己写的稳定需求。从我个人实践的角度,用这些所谓的外置的代码生成器,一旦数据库表结构生成变化,就需要重新生成代码并拷贝进项目。本来代码生成就不是只针对对象持久化方面,也不是只有外置的方式,甚至在我看来外置的方式就是YY。
代码生成这个东西,生成的应该是经过实践的、稳定的、可以自动生成的代码。如果对生成的代码理解都很困难还在尝试写自己的代码生成器,我觉得不好。写代码生成器,如果抛开代码生成产生的根源和要解决的问题,一再的强调一些不相关的东西,却一直回避到底如何在应用中加快项目进度、提高效率等这些内容,对初学者真的是很不好的影响。一个编码能力很差(这么说不表示我编码能力强,我就是很弱的那种),阅读代码能力都不行的,公布一个代码生成器,你这是闹哪出呢。
也许有人说,初学者可以在自己编写代码生成的过程中学到很多知识,比如界面和控件、模板等,这是另一种方式的自欺欺人。大多外置代码生成器都不是web方式的,如果工作中一直从事asp.net开发,那所谓的界面和控件学到的知识还不如去学学自定义web控件开发了,除了代码生成,学到的模板知识在其他哪些方面基本没啥作用。毕竟所有初学者都遇到这种必须用模板的需求只能是YY。
通过查找发现相似代码,进行重构,引入框架或代码生成,本身就对代码能力有一定的要求,一些基础的代码实现和代码结构都搞不懂,就想做个会有很多人使用的某某代码生成器,既浪费了自己的时间又误导了初学者,这样不好。我就有过这样的经历,希望能对别人也起到一些警醒的作用,在本身阅读代码和写一些基础代码的能力都没有的时候,别跟风,别浮躁,努力提高自己的基础,即使研究代码生成,也从加快项目进度的角度出发,把精力用在集成在IDE中的动态代码生成上,要有一种追根溯源,立足实用的态度,不要看人家把msdn的示例代码改一改发个随笔说成自己原创,你就模仿,也不要看别人发了很多新技术的扫盲或入门系列很火,你就模仿。更不要看一些人用标题忽悠了很多人评论,你也照着做。搞不清楚来龙去脉,不要去学人家抛什么“XX技术无用论”,用"最XX的XX"之类的眼球文。即使能获得很多不明真相的小白的推崇,误导了众多停留在索要源代码为目标的初学者,也不能对自己起到任何提升的作用。
Code Snippet
<#@ template debug="false" hostspecific="True" Language="C#" #>
<#@ output extension=".cs" #>
<#@ Assembly Name="EnvDTE" #>
<#@ Import Namespace="EnvDTE" #>
<#@ Assembly Name="System.Xml" #>
<#@ Import Namespace="System.Xml" #>
<#@ Assembly Name="System.Data" #>
<#@ Import Namespace="System.Data" #>
<#@ Import Namespace="System.Data.Common" #>
<#@ Assembly Name="System.Configuration" #>
<#@ Import Namespace="System.Configuration" #>
using System;
namespace <#
DTE dte = ((DTE)((IServiceProvider)this.Host).GetService(typeof(DTE)));
Project project = null;
try
{
project = dte.SelectedItems.Item(1).ProjectItem.ContainingProject;
}
catch
{
project = dte.SelectedItems.Item(1).Project;
}
this.Write(project.Name);
#>.Model
{
<#
ProjectItem configItem = null;
try
{
configItem = project.ProjectItems.Item("web.config");
}
catch
{
configItem = project.ProjectItems.Item("app.config");
}
XmlDocument configDoc = new XmlDocument();
configDoc.Load(configItem.Document.FullName);
XmlNode node = configDoc.SelectSingleNode("//configuration//connectionStrings//add[@name='ConnectionString']");
string providerName = node.Attributes["providerName"].Value;
string connectionString = node.Attributes["connectionString"].Value;
DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
using (DbConnection conn = factory.CreateConnection())
{
conn.ConnectionString = connectionString;
conn.Open();
DataTable schema = conn.GetSchema("TABLES");
for (int i = 0; i < schema.Rows.Count; i++)
{
//
}
conn.Close();
}
#>
}
在AddIn中也可以直接使用CodeModel或FileCodleModel直接进行代码生成,如果通过T4,可以通过调用Solution.FindProjectItem找到T4文件,通过Open和Save方法让T4模板自动运行更新代码来达到动态更新的目的。
后记
T4的在我的电脑上实在是慢,每次总要弄的VS卡住一小会,如果在AddIn中直接生成代码又失去了模板的灵活性,考虑在AddIn中先生成中间映射文件,再通知代码生成程序来调用T4的模板方式或其他方式来生成代码,也许效果会更好些。对于代码生成,我现在的理解就是应该集成到IDE中并可以动态调用,做到生成代码不能改动,重新生成十分方便,将由于结构变化导致需要调整的代码部分的工作量压缩到最小。每隔一段时间,园子里总会热一段代码生成相关的话题。我希望尽量不误导初学者,尤其是那些说自己的代码生成器生成大部分代码的,提高了多少倍工作效率的,要么是基本不提需求变化,要么是变化了很少改动结构,或者根本是自己写的稳定需求。从我个人实践的角度,用这些所谓的外置的代码生成器,一旦数据库表结构生成变化,就需要重新生成代码并拷贝进项目。本来代码生成就不是只针对对象持久化方面,也不是只有外置的方式,甚至在我看来外置的方式就是YY。
代码生成这个东西,生成的应该是经过实践的、稳定的、可以自动生成的代码。如果对生成的代码理解都很困难还在尝试写自己的代码生成器,我觉得不好。写代码生成器,如果抛开代码生成产生的根源和要解决的问题,一再的强调一些不相关的东西,却一直回避到底如何在应用中加快项目进度、提高效率等这些内容,对初学者真的是很不好的影响。一个编码能力很差(这么说不表示我编码能力强,我就是很弱的那种),阅读代码能力都不行的,公布一个代码生成器,你这是闹哪出呢。
也许有人说,初学者可以在自己编写代码生成的过程中学到很多知识,比如界面和控件、模板等,这是另一种方式的自欺欺人。大多外置代码生成器都不是web方式的,如果工作中一直从事asp.net开发,那所谓的界面和控件学到的知识还不如去学学自定义web控件开发了,除了代码生成,学到的模板知识在其他哪些方面基本没啥作用。毕竟所有初学者都遇到这种必须用模板的需求只能是YY。
通过查找发现相似代码,进行重构,引入框架或代码生成,本身就对代码能力有一定的要求,一些基础的代码实现和代码结构都搞不懂,就想做个会有很多人使用的某某代码生成器,既浪费了自己的时间又误导了初学者,这样不好。我就有过这样的经历,希望能对别人也起到一些警醒的作用,在本身阅读代码和写一些基础代码的能力都没有的时候,别跟风,别浮躁,努力提高自己的基础,即使研究代码生成,也从加快项目进度的角度出发,把精力用在集成在IDE中的动态代码生成上,要有一种追根溯源,立足实用的态度,不要看人家把msdn的示例代码改一改发个随笔说成自己原创,你就模仿,也不要看别人发了很多新技术的扫盲或入门系列很火,你就模仿。更不要看一些人用标题忽悠了很多人评论,你也照着做。搞不清楚来龙去脉,不要去学人家抛什么“XX技术无用论”,用"最XX的XX"之类的眼球文。即使能获得很多不明真相的小白的推崇,误导了众多停留在索要源代码为目标的初学者,也不能对自己起到任何提升的作用。
相关文章推荐
- Visual Studio动态代码生成的实现基础
- YbSoftwareFactory 代码生成插件【二十四】:MVC中实现动态自定义路由
- js+插件实现代码复制及动态生成二维码扫描、分享到朋友圈QQ空间功能
- 利用Refly和CodeDom实现代码的动态生成和动态编译
- 浅谈静态代码生成和动态代码生成
- 利用Refly和CodeDom实现代码的动态生成和动态编译
- lua里实现类似宏定义,动态生成代码
- YbSoftwareFactory 代码生成插件【二十二】:CMS基础功能的实现
- Struts2实现生成动态验证码并验证实例代码
- 使用CODEDOM动态实现代码的生成,编译
- c#语言asp.net实现treeview控件读数据库动态生成树的代码
- Android基础:代码中实现界面动态布局
- 使用CODEDOM动态实现代码的生成,编译
- 使用CodeDOM实现代码生成及动态编译
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
- 微信小程序动态生成二维码的实现代码
- js+插件实现代码复制及动态生成二维码扫描、分享到朋友圈QQ空间功能
- 用.Net的动态代码生成功能实现AOP
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架