zoukankan      html  css  js  c++  java
  • 使用T4模板生成代码的学习

      之前做项目使用的都是Db First,直接在项目中添加Entity Framework,使用T4模板(T4模板引擎之基础入门)生成DAL BLL层等(T4模板是一个同事给的,也没有仔细研究,代码如下:)

    复制代码
    <#@ template language="C#" debug="false" hostspecific="true"#>
    <#@ include file="EF.Utility.CS.ttinclude"#>
    <#@ output extension=".cs"#>
    <#
    
    CodeGenerationTools code = new CodeGenerationTools(this);
    MetadataLoader loader = new MetadataLoader(this);
    CodeRegion region = new CodeRegion(this, 1);
    MetadataTools ef = new MetadataTools(this);
    
    string inputFile = @"..\TestProject.Model\EFData.edmx";
    
    EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
    string namespaceName = code.VsNamespaceSuggestion();
    
    EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
    
    #>
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Entity;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Text;
    using DianXin.TianYi.Model;
    using DianXin.TianYi.IDAL;
    
    namespace TestProjectDAL
    {    
        <#    
        foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
        {       
        #>            
            public partial class <#=entity.Name#>DAL : BaseDAL<<#=entity.Name#>>, I<#=entity.Name#>DAL {}
        <#
        }
        #>
    }
    复制代码

    现在突然想用一下Code First改变一下(觉得直接在Model上加特性标签,挺爽的,省去再使用“BuddyClass”做验证了),但突然发现上面的代码不能用了,令人感觉有点小郁闷(其实是个人比较懒了),就仔细翻看一下这方面的资料(关于上面代码可以参考:实体框架实用工具.ttinclude文件)。但觉得网上没有介绍在CodeFirst中使用T4生成DAL层的文章或者文章有点太老了,里面方法没有实验成功,也有点让人看不懂。经过七拼八揍终于被我整出来了,其中也遇到了几个小问题,就在这记录一下。

    1.关于错误" 正在编译转换: 未能找到类型或命名空间名称“TestProject”(是否缺少 using 指令或程序集引用?) ",是因为直接在T4模板里使用<#@ import namespace="TestProject.Model" #>,才报的这个错,这里要说明一下,如果添加系统引用是没有问题。(eg: <#@ important namespace="System.Data.SqlClient" #>),T4测试代码如下:

    复制代码
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="TestProject.Model" #>
    <#@ output extension=".cs" #>
    复制代码

    解决此问题可以简单分为3步:

    第1步,先引入dll文件

    代码如下:

    复制代码
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ assembly name="$(SolutionDir)TestProject.ModelinDebugTestProject.Model.dll" #>
    <#@ output extension=".cs" #>
    复制代码

    其中”$(SolutionDir)“是指解决方案目录,这种称做VS宏的方式。具体有以下几个系统VS宏:

    $(SolutionDir) 当前项目所在解决方案目录
    $(ProjectDir) 当前项目所在目录
    $(TargetPath) 前项目编译输出文件绝对路径
    $(TargetDir) 当前项目编译输出目录,即web项目的Bin目录,控制台、类库项目bin目录下的debug或release目录(取决于当前的编译模式)

    第2步:在第1步的基础上添加命名空间就可以了,代码如下:

    复制代码
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ assembly name="$(SolutionDir)TestProject.ModelinDebugTestProject.Model.dll" #>
    <#@ import namespace="TestProject.Model" #>
    <#@ output extension=".cs" #>
    复制代码

    第3步:就可以直接写代码了,我的做法是先获得TestContext(这个类继承了DbContext)里的所有属性,判断属性的类型名中包含DbSet的属性,然后再获得属性里的泛型类型数组,就可以获得类。示例代码如下:

    TestContext:

    复制代码
    public partial class TestContext : DbContext
    {
        public TestContext() : base("TestDatabase") { }
    
        public DbSet<Teacher> Teachers { get; set; }
            
        public DbSet<Person> Persons { get; set; }
    
        public DbSet<Student> Students { get; set; }
    }
    复制代码

    EntityClassInfo:(通过该类可以获得TestContext里所有类型为DbSet的类名称)

    复制代码
    public class EntityClassInfo
        {
            public EntityClassInfo()
            {
                List<string> classNameList = new List<string>();
                PropertyInfo[] properties = typeof(TestContext).GetProperties();    // 获得对象所有属性
                foreach (var property in properties)
                {
                    string propertyType = property.PropertyType.Name;   // 获得属性类型名称
                    if (propertyType.Contains("DbSet"))     // 判断是否为实体集合
                    {
                        Type[] genericTypes = property.PropertyType.GenericTypeArguments;   // 获得泛型类型数组
                        foreach (var type in genericTypes)
                        {
                            classNameList.Add(type.Name);   // 获得泛型类型名称 并添加到集合中
                        }
                    }
                }
                this.EntitiesList = classNameList;
            }
    
            public List<string> EntitiesList { get; set; }
        }
    复制代码

    T4代码:

    复制代码
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ assembly name="$(SolutionDir)TestProject.ModelinDebugTestProject.Model.dll" #>
    <#@ import namespace="TestProjectModel" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Reflection" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ output extension=".cs" #>
    <#
    var entity = new EntityClassInfo();
    foreach(var item in entity.EntitiesList)
    {#>
        <#=item#>
    <#}#>
    复制代码

    参考资料:解决T4模板的程序集引用出错(5种方案)

    就这样吧,如有错误之处,请大牛们指出,谢谢

    http://www.cnblogs.com/silencealone/p/4534757.html

    http://www.cnblogs.com/guomingfeng/p/mvc-ef-t4.html

  • 相关阅读:
    中断类型表
    ComboBox中Datasource、 DisplayMember和ValueMember 三个属性问题 初学者
    ComboBox中的 DataSourc、 DisplayMember 、 valueMember 属性顺序设置问题 初学者
    皮尔逊相关度评价(Pearson correlation Score)
    欧几里得距离评价(Euclidean Distance Score)
    Leonardo da Vince
    维基F#译文: 值与函数(中)
    维基F#译文: 值与函数(上)
    perl5的引用(perlreftut)
    维基F#译文:入门
  • 原文地址:https://www.cnblogs.com/xiaoshi657/p/4881601.html
Copyright © 2011-2022 走看看