Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to generate similar Code using T4 template in EF Code First

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces how to use T4 template to generate similar code in EF Code First, which has a certain reference value, and interested friends can refer to it. I hope you can learn a lot after reading this article.

I. Preface

At present, our data layer function has been relatively perfect, but there are many codes with high similarity, such as EntityConfiguration in charge of entity mapping, IEntityRepository and EntityRepository in charge of warehousing operations. And every time you add an entity type, you have to manually add a set of corresponding code, which is also a tiring work. If there is a solution that automatically generates these more similar codes according to the entity type, it will reduce a lot of boring work.

The "text template" (commonly known as T4) function provided by VS is a better solution. To add an entity type, you can automatically generate the corresponding class file by defining the entity type and then running the defined T4 template.

II. Tool preparation

In order to make better use of the T4 template feature, we need to install the following two plug-ins for VS:

Devart T4 Editor: provides smart prompts for VS.

T4 Toolbox: useful when generating multiple files.

Third, T4 code generation warm-up

(1) single file generation: HelloWorld.cs

Next, let's first experience one of the simplest T4 code generation features and output the simplest class file.

First, add a folder called T4 in GMF.Demo.Core.Data to store the T4 template files for the code within the living cost project. And add a "text template" item named HelloWorld.tt.

HelloWorld.tt is defined as follows:

Using System; namespace GMF.Demo.Core.Data.T4 {public class HelloWorld {private string _ word; public HelloWorld (string word) {_ word = word;}

Save the file directly (the generation of T4 will automatically trigger the generation when the template is saved and the template loses focus, etc. A class file with the same name will be generated at the current location of the template

The HelloWorld.cs is as follows:

Using System; namespace GMF.Demo.Core.Data.T4 {public class HelloWorld {private string _ word; public HelloWorld (string word) {_ word = word;}

In this way, our journey to HelloWorld is over. It's very simple.

(2) multiple file generation

The scheme for the current location scheme can only generate code like the following:

The generated files will be in the same directory as the T4 template, which will not be detailed here. You can refer to a simple version of Jiang Jinnan's T4 code generation "framework".

Multiple files of the project need to be generated into the specified folder, but you want to manage the T4 template uniformly. T4 template files are placed in the T4 folder, but the generated mapping file EntityConfiguration will be placed in the folder Configurations, and the warehousing operation files IEntityRepository and EntityRepository will be placed in the Repositories folder. And the generated code files should be automatically added to the solution, not just in the folder.

A simple way to achieve this requirement is to generate it through T4 Toolbox. If you want to know the details of T4Toolbox, you can use ILSpy to decompile the T4Toolbox.dll file to view the source code. If T4Toolbox is installed through the VS plug-in, it will be in the "C:\ Users\ Administrator\ AppData\ Local\ Microsoft\ VisualStudio\ 11.0\ Extensions\ dca4f0lt.jdx" folder (on my machine). Next, let's directly demonstrate the multi-file generation.

First, add a code template called HelloWorldTemplate.tt for T4 Toolbox.

This template will inherit from the CSharpTemplate class of T4 Toolbox:

Using System; namespace GMF.Demo.Core.Data.T4 {public class {private string _ word; public (string word) {_ word = word;}

A className parameter is defined in the template class to receive a value that represents the name of the class to be generated. All the code that generates the class is written as a string in the overridden TransformText method.

Then define a T4 template file HelloWorldMulti.tt, which is used to call the code template defined above to generate the code file.

The above is the executor of the entire T4 template, in the executor, to reference all the required class library files, namespaces, included template files, and so on.

Finally, the file is generated by calling the RenderToFile (string filename) method defined in the Template base class of T4 Toolbox to generate each file, and the input parameter is the full name of the generated file. Here, the build will look like this:

The HelloWorld1.cs, HelloWorld2.cs, HelloWorld3.cs files are generated in the outPPath folder, and an empty HelloWorldMulti.cs class file is generated in the folder where the HelloWorldMulti.tt is located.

4. Generate similar codes related to data layer entities

(1) preparation for generation

Our generated code is completely dependent on the business entity, so we need a class to extract and encapsulate the information of the business entity.

Namespace GMF.Component.Tools.T4 {/ T4 entity model information class / public class T4ModelInfo {/ get the module name of the model / public string ModuleName {get; private set } / get the model name / public string Name {get; private set;} / get the model description / public string Description {get; private set;} public IEnumerable Properties {get; private set } public T4ModelInfo (Type modelType) {var @ namespace = modelType.Namespace; if (@ namespace = = null) {return;} var index = @ namespace.LastIndexOf ('.') + 1; ModuleName = @ namespace.Substring (index, @ namespace.Length-index) Name = modelType.Name; var descAttributes = modelType.GetCustomAttributes (typeof (DescriptionAttribute), true); Description = descAttributes.Length = = 1? (DescriptionAttribute) descAttributes [0]) .Description: Name; Properties = modelType.GetProperties ();}

In addition, the code generated through the template is different from our handwritten code as follows:

Handwritten code can be defined freely, and the generated code is generated according to the template, which must follow the specification of the template definition.

Changes to the handwritten code can be saved permanently, and changes to the generated code will be lost after the next generation, that is, the generated code should not be modified.

Based on the above differences, I propose the following solutions to solve the problem of modifying the generated code

The class generated by the template should be defined as a partial class (partial class) as far as possible, and another partial class with the same name can be defined to modify when it needs to be modified and extended.

For functions that need to be externally implemented, partial methods are defined to provide extensions.

The class file name that generates the code changes the extension from ".cs" to "generated.cs" to distinguish the generated code from the handwritten code file.

(2) generate similar codes related to entities

1. Generate entity mapping configuration class

Entity mapping configuration class template EntityConfigurationTemplate.tt definition:

/ / this code is generated by the tool. / / A change to this file may result in incorrect behavior and will be lost if / / the code is regenerated. / / if there is a new requirement outside this generated code, please create a partial class with the same name under the same namespace to implement the ConfigurationAppend partial method. / Copyright (c) 2013 GMFCN.All rights reserved. / / CLR version: 4.0.30319.239 / / Development Organization: Guo Mingfeng @ China / / Company website: http://www.gmfcn.net / / Project: GMF.Demo.Core.Data / / Generation time: /-- -using System Using System.Data.Entity.ModelConfiguration; using System.Data.Entity.ModelConfiguration.Configuration; using GMF.Component.Data; using GMF.Demo.Core.Models Namespace GMF.Demo.Core.Data.Configurations {/ entity class-datasheet mapping-/ internal partial class Configuration: EntityTypeConfiguration, IEntityMapper {/ entity class-Datasheet mapping constructor-/ public Configuration () {ConfigurationAppend () } / additional data mapping / partial void ConfigurationAppend () / registers the current entity mapping object with the current data access context entity mapping configuration registry / entity mapping configuration registry public void RegistTo (ConfigurationRegistrar configurations) {configurations.Add (this);}

Generate template caller EntityCodeScript.tt definition

Typeof (Entity) .IsAssignableFrom (m) & &! m.IsAbstract); foreach (Type modelType in modelTypes) {T4ModelInfo model = new T4ModelInfo (modelType); / / entity mapping class EntityConfigurationTemplate config = new EntityConfigurationTemplate (model); string path = string.Format (@ "{0}\ Configurations", projectPath); config.Output.Encoding = Encoding.UTF8 Config.RenderToFile (Path.Combine (path, config.FileName));} # >

The caller obtains all the entity type information that the base class is Entity and is not an abstract class from the business entity assembly GMF.Demo.Core.Models.dll through reflection, and then calls the template to generate the entity configuration class files one by one.

For example, the mapping file LoginLogConfiguration.generated.cs for the generated login record information (LoginLog) is as follows:

/ / this code is generated by the tool. / / A change to this file may result in incorrect behavior and will be lost if / / the code is regenerated. / / if there is a new requirement outside this generated code, please create a partial class with the same name under the same namespace to implement the LoginLogConfigurationAppend partial method. / Copyright (c) 2013 GMFCN.All rights reserved. / / CLR version: 4.0.30319.239 / / Development Organization: Guo Mingfeng @ China / / Company website: http://www.gmfcn.net / / Project: GMF.Demo.Core.Data / / Generation time: 2013-06-16 17:45 /- -using System Using System.Data.Entity.ModelConfiguration; using System.Data.Entity.ModelConfiguration.Configuration; using GMF.Component.Data; using GMF.Demo.Core.Models Namespace GMF.Demo.Core.Data.Configurations {/ entity class-data table mapping-login record information / internal partial class LoginLogConfiguration: EntityTypeConfiguration IEntityMapper {/ entity class-Datasheet mapping constructor-login record information / public LoginLogConfiguration () {LoginLogConfigurationAppend () } / additional data mapping / partial void LoginLogConfigurationAppend () / registers the current entity mapping object with the current data access context entity mapping configuration registry / entity mapping configuration registry public void RegistTo (ConfigurationRegistrar configurations) {configurations.Add (this);}

To configure the N 1 relationship between login information and user information, simply add a partial class LoginLogConfiguration and implement the classification method LoginLogConfigurationAppend.

Namespace GMF.Demo.Core.Data.Configurations {partial class LoginLogConfiguration {partial void LoginLogConfigurationAppend () {HasRequired (m = > m.Member) .WithMany (n = > n.LoginLogs);}

two。 Generate physical warehousing interface

Entity mapping configuration class template EntityConfigurationTemplate.tt definition:

/ / this code is generated by the tool. / / A change to this file may result in incorrect behavior and will be lost if / / the code is regenerated. / / if there is a new requirement outside this generated code, please create a partial class with the same name under the same namespace to implement it. / Copyright (c) 2013 GMFCN.All rights reserved. / / CLR version: 4.0.30319.239 / / Development Organization: Guo Mingfeng @ China / / Company website: http://www.gmfcn.net / / Project: GMF.Demo.Core.Data / / Generation time: /-- -using System Using GMF.Component.Data; using GMF.Demo.Core.Models; namespace GMF.Demo.Core.Data.Repositories {/ data access layer interface-/ public partial interface IRepository: IRepository {}}

Accordingly, add the template invocation code to the caller EntityCodeScript.tt (shown in lines 11-15 below):

Foreach (Type modelType in modelTypes) {T4ModelInfo model = new T4ModelInfo (modelType); / / entity mapping class EntityConfigurationTemplate config = new EntityConfigurationTemplate (model); string path = string.Format (@ "{0}\ Configurations", projectPath); config.Output.Encoding = Encoding.UTF8; config.RenderToFile (Path.Combine (path, config.FileName)) / / physical warehousing operation interface IEntityRepositoryTemplate irep= new IEntityRepositoryTemplate (model); path = string.Format (@ "{0}\ Repositories", projectPath); irep.Output.Encoding = Encoding.UTF8; irep.RenderToFile (Path.Combine (path, irep.FileName));}

The generated login record information warehousing operation API ILoginLogRepository.generated.cs:

/ / this code is generated by the tool. / / A change to this file may result in incorrect behavior and will be lost if / / the code is regenerated. / / if there is a new requirement outside this generated code, please create a partial class with the same name under the same namespace to implement it. / Copyright (c) 2013 GMFCN.All rights reserved. / / CLR version: 4.0.30319.239 / / Development Organization: Guo Mingfeng @ China / / Company website: http://www.gmfcn.net / / Project: GMF.Demo.Core.Data / / Generation time: 2013-06-16 17:56 /- -using System Using GMF.Component.Data; using GMF.Demo.Core.Models; namespace GMF.Demo.Core.Data.Repositories {/ data access layer interface-login record information / public partial interface ILoginLogRepository: IRepository {}}

If the warehousing operations defined in IRepository do not meet the requirements of login record warehousing operations, you only need to add a corresponding partial interface in which the requirements can be defined. There are currently no additional requirements, so no additional definition is needed.

3. Generate entity warehousing implementation

The implementation of physical warehousing operation is similar to the warehousing operation interface, which is skipped here.

After the generation is complete, the code structure is as follows:

If you add or remove an entity, you only need to rerun the calling template EntityCodeScript.tt to regenerate the new code.

Thank you for reading this article carefully. I hope the article "how to use T4 template to generate similar code in EF Code First" shared by the editor will be helpful to everyone. At the same time, I also hope that you will support and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report