1、问题描述
对一个程序做性能优化,发现程序里会大量创建动态对象,是影响性能的一个瓶颈。程序里都是采用Activator.CreateInstance(Type)的方法,记得在codeproject看过一篇文章(原文在此:Dynamic Objects, Factories, and Runtime Machines to Boost Performance),对动态创建对象的几种方式进行效率对比,Activator.CreateInstance是效率较低的一种。采用FormatterServices.GetUninitializedObject得到一个未初始化的类,再调用类的工厂方法,效率有大幅提高。下面是简单的代码说明。更多内容请参见上文提到的文章。 因此,决定采用FormatterServices.GetUninitializedObject方法来代替Activator.CreateInstance(Type)。整个项目有两个基类以及从该基类继承的大量子类(数目大概有100+)需要更改,而且继承关系最深达到5层。代码的修改工作量不小。
2、解决办法
2.1 复制粘贴
大概是最常规也最无趣的方法,我在复制了10个左右的类后实在受不了这种单调和枯燥,放弃了。
2.2 Code Snippet
复制的进阶,就是用Code Snippet了。把相同代码做成Snippet,效率有大幅提高。Snippet文件内容如下: 在上面的snippet中,值得一提的是,使用了snippet function。即先定义了一个Literal,名称为RetType,代表工厂方法返回类型。我们知道不同的子类,工厂方法的函数签名相同,不同的是返回该类的实例。即RetType的值要等于被插入的类的名称。于是我们为RetType这个Literal提供了一个function,ClassName(),该函数返回snippet所在类的名称。
实际我们不需要手工来写这个文件,这里推荐Code Snippet Editor这个小 工具。
2.3 CodeModel
现在只需要找到需要更改的类,敲下快捷键fm,再双击tab就ok了,委实比当初复制、编辑幸福多了。但人心难足,Snippet还是有不爽的地方:
1、找到并打开所有要修改的类(100+啊兄弟,项目里每个类都是一个单独文件)不停地重复按键,也是挺无聊的活。更重要的是,要保证不能遗漏——上文说了,很多子类都经过了多达5层的继承……
2、不同的基类要重新编制一个snippet。另外考虑到,如果以后别的项目要有类似的更改呢?如果项目是用VB.NET而不是c#呢?。。。。
看来,最好的解决办法是写一个AddIn了。
简单分析下任务,其实就是两个:1、寻找项目中要添加工厂方法的基类及所有派生类。2、为这些类添加一个相应的工厂函数。
很自然需要用到CodeModel。
关于VS的扩展开发,推荐园子里Anders Cui的 系列文章。而Anders Cui的系列恰好没有写关于CodeModel的内容,既有珠玉在前,所以小可也就斗胆续貂,简单写写关于CodeModel的内容。
直接用Vs2008新建项目,选择“Visual Stduio外接程序”,选择使用c# 语言开发,然后一路默认,编辑器就自动为你生成了一个AddIn项目。该项目已经自动生成了大部分代码,包括将的AddIn程序添加到工具 菜单上等。接下来只需要将需要执行的代码加入到Exec函数中即可。
我们再在项目中添加一个含文本框的窗体,作为输入界面,输入项目中要添加工厂方法的基类的全名(含命名空间)。接下来就是利用CodeModel寻找该类及其派生类,并添加工厂方法。还是代码说话吧,相关函数我在注释里都有说明,另外可以查询msdn。 完整代码可以在这里下载: 附件: AddFactoryMethod.rar (下载 0 次)。
3、一些问题
3.1 CodeClass的属性DerivedTypes没有实现。否则寻找指定类的所有派生类将更为简化,程序更简单。
3.2 CodeClass.AddFunction方法,第2和第5个参数,使用示例代码以外的参数值,均会出现异常。Bug??所以示例最后被迫使用ReplaceText来完成加入虚函数的任务。希望有高手指点一下。
3.3 CodeModel中大部分集合,特别是有item属性但item非默认属性者,使用下标索引时,从1而非0开始。EnvDTE命名空间中其他集合大概也是。或者,推而广之,涉及到VSTA开发的(如VSTO),集合一般下标从1开始。毕竟这些领域还是VB为主。
3.4 和本文无关——后台编辑器在编辑代码的时候很不好用啊。尤其选择折叠代码的时候,居然不能正常显示。。。我浏览器的问题麽?
4、参考文献
1、《 Dynamic Objects, Factories, and Runtime Machines to Boost Performance》 by Philip Liebscher
2、《 Creating a C# Class using the CodeModel Object》 MSDN
3、《 如何:使用 CodeModel 对象分析 Visual Basic 代码》 MSDN
4、关于Vs扩展的系列文章: Visual Studio 2008 可扩展性开发(九):总结篇
对一个程序做性能优化,发现程序里会大量创建动态对象,是影响性能的一个瓶颈。程序里都是采用Activator.CreateInstance(Type)的方法,记得在codeproject看过一篇文章(原文在此:Dynamic Objects, Factories, and Runtime Machines to Boost Performance),对动态创建对象的几种方式进行效率对比,Activator.CreateInstance是效率较低的一种。采用FormatterServices.GetUninitializedObject得到一个未初始化的类,再调用类的工厂方法,效率有大幅提高。下面是简单的代码说明。更多内容请参见上文提到的文章。 因此,决定采用FormatterServices.GetUninitializedObject方法来代替Activator.CreateInstance(Type)。整个项目有两个基类以及从该基类继承的大量子类(数目大概有100+)需要更改,而且继承关系最深达到5层。代码的修改工作量不小。
2、解决办法
2.1 复制粘贴
大概是最常规也最无趣的方法,我在复制了10个左右的类后实在受不了这种单调和枯燥,放弃了。
2.2 Code Snippet
复制的进阶,就是用Code Snippet了。把相同代码做成Snippet,效率有大幅提高。Snippet文件内容如下: 在上面的snippet中,值得一提的是,使用了snippet function。即先定义了一个Literal,名称为RetType,代表工厂方法返回类型。我们知道不同的子类,工厂方法的函数签名相同,不同的是返回该类的实例。即RetType的值要等于被插入的类的名称。于是我们为RetType这个Literal提供了一个function,ClassName(),该函数返回snippet所在类的名称。
实际我们不需要手工来写这个文件,这里推荐Code Snippet Editor这个小 工具。
2.3 CodeModel
现在只需要找到需要更改的类,敲下快捷键fm,再双击tab就ok了,委实比当初复制、编辑幸福多了。但人心难足,Snippet还是有不爽的地方:
1、找到并打开所有要修改的类(100+啊兄弟,项目里每个类都是一个单独文件)不停地重复按键,也是挺无聊的活。更重要的是,要保证不能遗漏——上文说了,很多子类都经过了多达5层的继承……
2、不同的基类要重新编制一个snippet。另外考虑到,如果以后别的项目要有类似的更改呢?如果项目是用VB.NET而不是c#呢?。。。。
看来,最好的解决办法是写一个AddIn了。
简单分析下任务,其实就是两个:1、寻找项目中要添加工厂方法的基类及所有派生类。2、为这些类添加一个相应的工厂函数。
很自然需要用到CodeModel。
关于VS的扩展开发,推荐园子里Anders Cui的 系列文章。而Anders Cui的系列恰好没有写关于CodeModel的内容,既有珠玉在前,所以小可也就斗胆续貂,简单写写关于CodeModel的内容。
直接用Vs2008新建项目,选择“Visual Stduio外接程序”,选择使用c# 语言开发,然后一路默认,编辑器就自动为你生成了一个AddIn项目。该项目已经自动生成了大部分代码,包括将的AddIn程序添加到工具 菜单上等。接下来只需要将需要执行的代码加入到Exec函数中即可。
我们再在项目中添加一个含文本框的窗体,作为输入界面,输入项目中要添加工厂方法的基类的全名(含命名空间)。接下来就是利用CodeModel寻找该类及其派生类,并添加工厂方法。还是代码说话吧,相关函数我在注释里都有说明,另外可以查询msdn。 完整代码可以在这里下载: 附件: AddFactoryMethod.rar (下载 0 次)。
3、一些问题
3.1 CodeClass的属性DerivedTypes没有实现。否则寻找指定类的所有派生类将更为简化,程序更简单。
3.2 CodeClass.AddFunction方法,第2和第5个参数,使用示例代码以外的参数值,均会出现异常。Bug??所以示例最后被迫使用ReplaceText来完成加入虚函数的任务。希望有高手指点一下。
3.3 CodeModel中大部分集合,特别是有item属性但item非默认属性者,使用下标索引时,从1而非0开始。EnvDTE命名空间中其他集合大概也是。或者,推而广之,涉及到VSTA开发的(如VSTO),集合一般下标从1开始。毕竟这些领域还是VB为主。
3.4 和本文无关——后台编辑器在编辑代码的时候很不好用啊。尤其选择折叠代码的时候,居然不能正常显示。。。我浏览器的问题麽?
4、参考文献
1、《 Dynamic Objects, Factories, and Runtime Machines to Boost Performance》 by Philip Liebscher
2、《 Creating a C# Class using the CodeModel Object》 MSDN
3、《 如何:使用 CodeModel 对象分析 Visual Basic 代码》 MSDN
4、关于Vs扩展的系列文章: Visual Studio 2008 可扩展性开发(九):总结篇