软件的程序代码的生成方法及装置
技术领域
本发明涉及计算机领域,具体而言,涉及一种软件的程序代码的生成方法及装置。
背景技术
依赖属性是WPF和Silverlight的基石之一,设计依赖属性的目的就是根据多个不同的输入动态计算出属性值,这些不同的输入包括:资源文件、绑定、动画、属性继承等,现有技术对于依赖属性的定义通常采取如下部分代码:
从上述代码可知,定义依赖属性非常较为繁琐,每次定义都要手动输入大量内容,但是从中可以发现规律,即除了上述斜体字,其他的字符都是固定不变的,现有技术中解决的方案比如visual studio或Resharper等工具都可以在界面上自动生成上述固定不变的字符串,在上述代码中的IsSpinning或bool等属性值上使用斜体形式等特殊方式进行标识,用户只需针对带有特殊标识的属性值进行输入,以解决上述重复输入繁琐的问题。
这里需要说明的是,上述代码中多次重复出现依赖属性名称,例如,IsSpinning,用户在每次修改依赖属性的时候都要多次进行重复的输入,最后生成修改后的依赖属性的代码,代码生成效率较低。
针对现有技术在生成具有重复部分的代码时,需要针对重复的部分手动依次输入,导致生成代码效率低的问题,目前尚未提出有效的解决方案。
发明内容
本发明的主要目的在于提供一种软件的程序代码的生成方法及装置,以解决现有技术要生成具有重复部分的代码要针对重复的部分手动依次输入,生成代码效率低的问题。
为了实现上述目的,根据本发明实施例的一个方面,提供了一种软件的程序代码的生成方法,该方法包括:定义标记类并将标记类应用到程序集中的目标类中,生成新的程序集,其中,标记类用于标记目标类的属性特征,目标类为实现目标功能的程序代码;通过T4模板来读取新的程序集,获取新的程序集中包含标记类的对象;采用反射的方式获取标记类中的每个对象中的属性值;将标记类中的每个对象中的属性值替换目标代码模板中的占位符,生成目标代码,其中,目标代码模板为预先定义的模板;将目标代码输出到程序集中的目标类中。
为了实现上述目的,根据本发明实施例的另一方面,提供了一种代码生成的装置。该装置包括:标记单元,用于定义标记类并将标记类应用到程序集中的目标类中,生成新的程序集,其中,标记类用于标记目标类的属性特征,目标类为实现目标功能的程序代码;获取单元,用于通过T4模板来读取新的程序集,获取新的程序集中包含标记类的对象;反射单元,用于采用反射的方式获取标记类中的每个对象中的属性值;代码生成单元,将标记类中的每个对象中的属性值替换目标代码模板中的占位符,生成目标代码,其中,目标代码模板为预先定义的模板;输出单元,用于将目标代码输出到程序集中的目标类中。
根据发明实施例,通过定义标记类并将标记类应用到程序集中的目标类中,生成新的程序集,其中,标记类用于标记目标类的属性特征,目标类为实现目标功能的程序代码;通过T4模板来读取新的程序集,获取新的程序集中包含标记类的对象;采用反射的方式获取标记类中的每个对象中的属性值;将标记类中的每个对象中的属性值替换目标代码模板中的占位符,生成目标代码,其中,目标代码模板为预先定义的模板;将目标代码输出到程序集中的目标类中。本发明解决了现有技术在生成具有重复部分的代码时,需要针对重复的部分手动依次输入,导致生成代码效率低的问题。
附图说明
构成本申请的一部分的附图用来提供对本发明的进一步理解,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
图1是根据本发明实施例的一的软件的程序代码的生成方法的流程图;
图2是根据本发明实施例的一的优选的软件的程序代码的生成方法的示意图;
图3是根据本发明实施例二的软件的程序代码的生成装置的结构示意图;以及
图4是根据本发明实施例二的优选的软件的程序代码的生成装置的结构示意图。
具体实施方式
需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。下面将参考附图并结合实施例来详细说明本发明。
为了使本技术领域的人员更好地理解本发明方案,下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分的实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都应当属于本发明保护的范围。
需要说明的是,本发明的说明书和权利要求书及上述附图中的术语“第一”、“第二”等是用于区别类似的对象,而不必用于描述特定的顺序或先后次序。应该理解这样使用的数据在适当情况下可以互换,以便这里描述的本发明的实施例。此外,术语“包括”和“具有”以及他们的任何变形,意图在于覆盖不排他的包含,例如,包含了一系列步骤或单元的过程、方法、系统、产品或设备不必限于清楚地列出的那些步骤或单元,而是可包括没有清楚地列出的或对于这些过程、方法、产品或设备固有的其它步骤或单元。
本申请术语解释如下:
Visual Studio:是微软为开发人员提供的开发工具
Resharper:是Visual Studio的一个插件,主要是提供很多便利的功能,提高开发效率
T4模板:集成在Visual Studio中代码生成工具,主要用于自动生成代码
分部类:就是将类拆分到多个文件中,每个文件是类的一部分,编译时将所有部分组合起来
分部方法:类似于分部类,就是将方法拆分到多个文件中,一个文件中给出方法定义,一个文件中给出方法实现
例子:
Attribute(特性):在基于.NET开发语言中,在.NET中定义的类、方法都是有元数据的,以类为例,类的名称、类型、命名空间,访问修饰符(public、private)这些都相当于元数据信息,编译好的程序集包含这些元数据信息。Attribute也是一种元数据信息,编译后程序集中保存了每个类的Attribute
反射:就是读取程序集的元数据,运行时创建类的实例,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射来访问它们。
实施例1:
本发明实施例提供了一种软件的程序代码的生成方法。如图1所示,该方法包括步骤如下:
步骤S101,定义标记类并将标记类应用到程序集中的目标类中,生成新的程序集,其中,标记类用于标记目标类的属性特征,目标类为实现目标功能的程序代码。
具体的,本实施例可以以生成依赖属性的代码为例进行阐述,本实施例可以首先定义标记类,上述标记类可以是DependencyPropertyAttribute,上述标记类可以包含对象,上述对象可以是依赖属性的至少一个特征,上述标记类DependencyPropertyAttribute则包含上述依赖属性的至少一个特征。可以使用T4模板将定义的标记类到需要生成依赖属性的程序集中,具体到程序集中需要生成依赖属性的目标类中。程序集中由于添加了标记类因而生成新的程序集。
步骤S103,通过T4模板来读取新的程序集,获取新的程序集中包含标记类的对象。
步骤S105,采用反射的方式获取标记类中的每个对象中的属性值。
步骤S107,将标记类中的每个对象中的属性值替换目标代码模板中的占位符,生成目标代码,其中,目标代码模板为预先定义的模板。
具体的,上述目标代码模板可以为生成依赖属性的模板,例如如下代码:
在上述代码中,占位符0、1、2、3可以对应上述标记类中的4个属性值。从上述依赖属性的模板中可以看到第零个占位符为依赖属性的名称,第一个占位符为依赖属性的类型,第二个占位符为依赖属性的拥有者,第三个占位符为依赖属性的默认值。读取到标记类的DependencyPropertyAttribute的四个属性值后,直接将上述四个占位符中替换即可。
步骤S109,将目标代码输出到程序集中的目标类中。
可选的,在新的程序集中生成依赖属性代码之后,如果要修改依赖属性定义的话,只需要修改DependencyPropertyAttribute的属性修改,不需要多处修改。比如以下的依赖属性的定义:
如果用户想修改依赖属性的名称,用户只需要修改上述代码中的斜字“IsSpinning”即可,程序集中所有依赖属性的名称都会自动随着改变,如果用户想往程序集里添加依赖属性的时候,也只需要在DependencyPropertyAttribute即标记类中添加一处就可以了。
可选的,在上面的依赖属性的模板中,定义了IsSpinningPropertyChangeCallback的分部方法,如果类需要定义这个回调函数的话,只需要实现这个分部方法就可以了。
本实施例通过定义标记类并将标记类应用到程序集中的目标类,再通过反射的方式读取上述标记类中的属性值,添加到预先定义的目标代码模板中,从而生成目标代码,上述目标代码中包含重复的部分。本实施例解决了现有技术在生成具有重复部分的代码时,需要针对重复的部分手动依次输入,导致生成代码效率低的问题。
可选的,步骤S101中定义标记类的步骤可以包括:
步骤S201,定义标记类的对象,其中标记类的对象包括至少一个属性,在生成依赖属性的实例中,上述至少一个属性可以为:名称、类型、拥有者和默认值。
具体的,上述标记类可以是DependencyPropertyAttribute,DependencyPropertyAttribute可以包含依赖属性的四个特征定义,如下表1:
表1:
PropertyName |
依赖属性的名称 |
Type |
依赖属性的类型 |
Owner |
依赖属性的拥有者 |
DefaultValue |
依赖属性的默认值 |
可选的,步骤S103,将标记类应用到程序集中的目标类中,生成新的程序集之前,本实施例提供的方法可以包括:
步骤S301,接收用户输入的参数,在标记类中生成属性值,其中,参数分别对应标记类中的对象。
具体的,用户可以输入参数,上述参数可以是用户希望在上述目标类中生成的依赖属性代码中的至少一个属性值例如,下面的这个例子:
可选的,步骤S103中通过T4模板来读取新的程序集,获取新的程序集中包含标记类的对象的步骤还可以包括:
步骤S301,并通过调用方法的方式依次读取新的程序集中所有的类和所有类中标记类的目标类,并获取标记类的对象。
具体的,在使用T4模板加载上述新的程序集后,可以通过简单方法调用,即可读取程序集中包含的所有类。从上述新的程序集中读取到类后,类中包含很多信息,其中就包括了DependencyPropertyAttribute的类,同样通过简单方法调用,就可以判断新的程序集中的筛选出哪些类是否了DependencyPropertyAttribute,即是否了DependencyPropertyAttribute。
优选的,在步骤S103,将标记类应用到程序集中的目标类中,生成新的程序集之前,本实施例提供的方法可以包括:
步骤S401,使用T4模板定义目标代码模板,其中,目标代码模板中包含至少一个属性,在生成依赖属性的实例上,上述至少一个属性可以为:名称、类型、拥有者和默认值,其中名称、类型、拥有者和默认值在目标代码模板中使用不同的占位符替换。
可选的,本实施例虽然以生成依赖属性为例描述本方案,但本实施例提供的方案部局限于依赖属性,例如下面的例子也可以使用本实施例提供的方法来解决
这个例子中CustomerId属性的生成,和依赖属性的生成同属一类问题,即需要输入许多内容,但是这些内容大部分都是重复的,只有一小部分内容是不一样的。这个属性的生成也可以通过Visual Studio和Resharper提供的功能实现,但是问题和依赖属性的问题是一样的,即不支持修改。使用该解决方案,也可以解决类似于这样的属性的生成。
以下本申请在具体场景下描述:
首先定义DependencyPropertyAttribute,这个Attribute包含了依赖属性的四个特征定义,如下表2:
表2:
PropertyName |
依赖属性的名称 |
Type |
依赖属性的类型 |
Owner |
依赖属性的拥有者 |
在每个定义依赖属性的类上DependencyPropertyAttribute,并指定依赖属性的上述四个特征,比如下面的这个例子:
使用T4模板和发射自动生成依赖属性,即读取程序集中所有包含DependencyPropertyAttribute的类,然后自动生成依赖属性,具体的逻辑如图2所示。
结合图2,这里需要说明的是:
加载程序集后,程序集中是记录了包含哪些类的,通过简单方法调用,即可读取程序集中包含的所有类。
从程序集中读取到类后,类中包含很多信息,其中就包括了哪些Attribute,同样通过简单方法调用,就可以判断类是否了某一个Attribute,即是否了DependencyPropertyAttribute。
如果已经获取到DependencyPropertyAttribute定义的话,要获取它定义的属性值的话,通过简单的属性调用即可。
依赖属性的模板如下:
从模板中可以看到第零个占位符为依赖属性的名称,第一个占位符为依赖属性的类型,第二个占位符为依赖属性的拥有者,第三个占位符为依赖属性的默认值。读取到每个类的DependencyPropertyAttribute的四个属性值后,直接将上述四个占位符中替换即可
如果要修改依赖属性的定义的话,只需要修改DependencyPropertyAttribute的属性即可,不需要多处修改。比如下面的依赖属性定义:
如果用户想修改依赖属性的名称,只需要修改斜体文字就可以了,不需要多处修改。当然添加依赖属性定义的时候,也只需要添加一处就可以了。
在上面的依赖属性的模板中,定义了IsSpinningPropertyChangeCallback的分部方法,如果类需要定义这个回调函数的话,只需要实现这个分部方法就可以了
实施例2:
本发明实施例还提供了一种软件的程序代码的生成装置。如图3所示,该装置可以包括:
标记单元301,用于定义标记类并将标记类应用到程序集中的目标类中,生成新的程序集,其中,标记类用于标记目标类的属性特征,目标类为实现目标功能的程序代码。
具体的,本实施例可以以生成依赖属性的代码为例进行阐述,本实施例可以采用首先定义标记类,上述标记类可以是DependencyPropertyAttribute,上述标记类可以包含对象,上述对象可以是依赖属性的至少一个特征,上述标记类DependencyPropertyAttribute则包含上述依赖属性的至少一个特征。可以使用T4模板将定义的标记类到需要生成依赖属性的程序集中,具体到程序集中需要生成依赖属性的目标类中。程序集中由于添加了标记类因而生成新的程序集。
获取单元303,用于通过T4模板来读取新的程序集,获取新的程序集中包含标记类的对象。
反射单元305,用于采用反射的方式获取标记类中的每个对象中的属性值。
代码生成单元307,将标记类中的每个对象中的属性值替换目标代码模板中的占位符,生成目标代码,其中,目标代码模板为预先定义的模板。
具体的,上述目标代码模板可以为依赖属性的模板,例如如下代码:
在上述代码中,占位符0、1、2、3可以对应上述标记类中的4个属性值。从上述依赖属性的模板中可以看到第零个占位符为依赖属性的名称,第一个占位符为依赖属性的类型,第二个占位符为依赖属性的拥有者,第三个占位符为依赖属性的默认值。读取到标记类的DependencyPropertyAttribute的四个属性值后,直接将上述四个占位符中替换即可。
输出单元309,用于将目标代码输出到程序集中的目标类中。
可选的,在新的程序集中生成依赖属性代码之后,如果要修改依赖属性定义的话,只需要修改DependencyPropertyAttribute的属性修改,不需要多处修改。比如以下的依赖属性的定义:
如果用户想修改依赖属性的名称,用户只需要修改上述代码中的斜字“IsSpinning”即可,程序集中所有依赖属性的名称都会自动随着改变,如果,用户想往程序集里添加依赖属性的时候,也只需要在DependencyPropertyAttribute即标记类中添加一处就可以了。
可选的,在上面的依赖属性的模板中,定义了IsSpinningPropertyChangeCallback的分部方法,如果类需要定义这个回调函数的话,只需要实现这个分部方法就可以了。
本实施例首先定义标记类并将标记类应用到程序集中的目标类,再通过反射的方式读取上述标记类中的属性值,添加到预先定义的目标代码模板中,从而生成目标代码,上述目标代码中包含重复的部分。本实施例解决了现有技术要生成具有重复部分的代码要针对重复的部分手动依次输入,生成代码效率低的问题。
可选的,上述标记单元301还包括:
标记模块3011,用于定义标记类的对象,其中标记类的对象包括至少一个属性,在生成依赖属性的实例中,上述至少一个属性可以为:名称、类型、拥有者和默认值。
具体的,上述标记类可以是DependencyPropertyAttribute,DependencyPropertyAttribute可以包含依赖属性的四个特征定义,如下表3:
表3:
PropertyName |
依赖属性的名称 |
Type |
依赖属性的类型 |
Owner |
依赖属性的拥有者 |
DefaultValue |
依赖属性的默认值 |
可选的,本实施提供的装置还可以包括:
处理单元401,用于接收用户输入的参数,在标记类中生成属性值,其中,上述参数分别对应标记类中的对象。
具体的,用户可以输入参数,上述参数可以是用户希望在上述目标类中生成的依赖属性代码中的至少一个属性值例如,下面的这个例子:
可选的,如图4所示,上述获取单元303还可以包括:
获取模块3031,加载新的程序集,并通过调用方法的方式依次读取新的程序集中所有的类和所有类中标记类的目标类,并获取标记类的对象。
具体的,在使用T4模板加载上述新的程序集后,可以通过简单方法调用,即可读取程序集中包含的所有类。从上述新的程序集中读取到类后,类中包含很多信息,其中就包括了DependencyPropertyAttribute的类,同样通过简单方法调用,就可以判断新的程序集中的哪些类是否了DependencyPropertyAttribute,即是否了DependencyPropertyAttribute。
可选的,本实施提供的装置还可以包括:
模板定义单元501,用于使用T4模板定义目标代码模板,其中,目标代码模板中包含至少一个属性,在生成依赖属性的实例中,上述至少一个属性可以为:名称、类型、拥有者和默认值,其中名称、类型、拥有者和默认值在目标代码模板中使用不同的占位符替换。
可选的,本实施例虽然以生成依赖属性为例描述本方案,但本实施例提供的方案部局限于依赖属性,例如下面的例子也可以使用本实施例提供的方法来解决:
这个例子中CustomerId属性的生成,和依赖属性的生成同属一类问题,即需要输入许多内容,但是这些内容大部分都是重复的,只有一小部分内容是不一样的。这个属性的生成也可以通过Visual Studio和Resharper提供的功能实现,但是问题和依赖属性的问题是一样的,即不支持修改。使用该解决方案,也可以解决类似于这样的属性的生成。
以下本申请在具体场景下描述:
首先定义DependencyPropertyAttribute,这个Attribute包含了依赖属性的四个特征定义,如下表4:
表4:
PropertyName |
依赖属性的名称 |
Type |
依赖属性的类型 |
Owner |
依赖属性的拥有者 |
DefaultValue |
依赖属性的默认值 |
在每个定义依赖属性的类上DependencyPropertyAttribute,并指定依赖属性的上述四个特征,比如下面的这个例子:
使用T4模板和发射自动生成依赖属性,即读取程序集中所有包含DependencyPropertyAttribute的类,然后自动生成依赖属性,具体的逻辑如图2所示。
结合图2,这里需要说明的是:
加载程序集后,程序集中是记录了包含哪些类的,通过简单方法调用,即可读取程序集中包含的所有类。
从程序集中读取到类后,类中包含很多信息,其中就包括了哪些Attribute,同样通过简单方法调用,就可以判断类是否了某一个Attribute,即是否了DependencyPropertyAttribute。
如果已经获取到DependencyPropertyAttribute定义的话,要获取它定义的属性值的话,通过简单的属性调用即可。
依赖属性的模板如下:
从模板中可以看到第零个占位符为依赖属性的名称,第一个占位符为依赖属性的类型,第二个占位符为依赖属性的拥有者,第三个占位符为依赖属性的默认值。读取到每个类的DependencyPropertyAttribute的四个属性值后,直接将上述四个占位符中替换即可
如果要修改依赖属性的定义的话,只需要修改DependencyPropertyAttribute的属性即可,不需要多处修改。比如下面的依赖属性定义:
如果用户想修改依赖属性的名称,只需要修改标红的文字就可以了,不需要多处修改。当然添加依赖属性定义的时候,也只需要添加一处就可以了。
在上面的依赖属性的模板中,定义了IsSpinningPropertyChangeCallback的分部方法,如果类需要定义这个回调函数的话,只需要实现这个分部方法就可以了。
需要说明的是,对于前述的各方法实施例,为了简单描述,故将其都表述为一系列的动作组合,但是本领域技术人员应该知悉,本发明并不受所描述的动作顺序的限制,因为依据本发明,某些步骤可以采用其他顺序或者同时进行。其次,本领域技术人员也应该知悉,说明书中所描述的实施例均属于优选实施例,所涉及的动作和模块并不一定是本发明所必须的。
在上述实施例中,对各个实施例的描述都各有侧重,某个实施例中没有详述的部分,可以参见其他实施例的相关描述。
在本申请所提供的几个实施例中,应该理解到,所揭露的装置,可通过其它的方式实现。例如,以上所描述的装置实施例仅仅是示意性的,例如单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些接口,装置或单元的间接耦合或通信连接,可以是电性或其它的形式。
作为分离部件说明的单元可以是或者也可以不是物理上分开的,作为单元显示的部件可以是或者也可以不是物理单元,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部单元来实现本实施例方案的目的。
另外,在本发明各个实施例中的各功能单元可以集成在一个处理单元中,也可以是各个单元单独物理存在,也可以两个或两个以上单元集成在一个单元中。上述集成的单元既可以采用硬件的形式实现,也可以采用软件功能单元的形式实现。
集成的单元如果以软件功能单元的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读取存储介质中。基于这样的理解,本发明的技术方案本质上或者说对现有技术做出贡献的部分或者该技术方案的全部或部分可以以软件产品的形式体现出来,该计算机软件产品存储在一个存储介质中,包括若干指令用以使得一台计算机设备(可为个人计算机、移动终端、服务器或者网络设备等)执行本发明各个实施例方法的全部或部分步骤。而前述的存储介质包括:U盘、只读存储器(ROM,Read‐Only Memory)、随机存取存储器(RAM,Random Access Memory)、移动硬盘、磁碟或者光盘等各种可以存储程序代码的介质。
以上仅为本发明的优选实施例而已,并不用于限制本发明,对于本领域的技术人员来说,本发明可以有各种更改和变化。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。