现有类库名为QS.Model在当前项目中
该类库中有6个模型 5个Model都继承自DataAccess
现在我们使用这5个类生成CRUE
现在修改BLLTemplate.tt模型的代码
<#+
public class BLLTemplate : CSharpTemplate
{
string name;
public BLLTemplate(string modelName)
{
name = modelName;
}
/// <summary>
/// 获取 生成的文件名,根据模型名定义
/// </summary>
public string FileName
{
get
{
return string.Format("{0}BLL.cs", EntityName);
}
}
/// <summary>
/// 实体名称
/// </summary>
public string EntityName
{
get
{
return name.Replace("Model", string.Empty);
}
}
public override string TransformText()
{
base.TransformText();
#>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test.BLL
{
/// <summary>
/// 逻辑层
/// </summary>
public partial class TestBLL
{
public void Select(){
}
public void Delete(){
}
public void Update(){
}
public void Add(){
}
}
}
<#+
return this.GenerationEnvironment.ToString();
}
}
#>
具体的实现功能自己写在方法里面
修改文本文档TextTemplate2.tt代码
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ Import Namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ output extension=".txt" #>
//这个必填 导入T4工具
<#@ include file="T4Toolbox.tt" #>
//这里填写bll模型的路径 当前TextTemplate2.tt目录下的Template文件夹里的BLLTemplate1.tt
<#@ include file="Template/BLLTemplate1.tt" #>
<#
//当前TextTemplate2.tt所在的模板路径
var currentPath = Path.GetDirectoryName(Host.TemplateFile);
//解决方案路径
string solutionPath = currentPath.Substring(0, currentPath.LastIndexOf("\\"));
//项目名称
string projectFullName = currentPath.Substring(currentPath.LastIndexOf("\\") + 1);
//实体文件所在路径
string modelFile = Path.Combine(solutionPath + @"\QS.Model\\bin\Debug\QS.Model.dll");
byte[] fileData = File.ReadAllBytes(modelFile);
Assembly assembly = Assembly.Load(fileData);
IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => !m.IsAbstract && m.IsClass && m.BaseType != null);
foreach (Type modelType in modelTypes)
{
//实例化bll模板
BLLTemplate bll= new BLLTemplate(modelType.Name);
string filePath= Path.Combine(currentPath,"bll", bll.FileName);
//创建文件
bll.RenderToFile(filePath);
}
#>
这里用到了反射 并使用字节的方式加载 是因为在生成过程中出现过 该dll被T4模板占用 故换成此方法
然后保存或者右键TextTemplate2.tt运行自定义模板
这里可以调试T4模板在TextTemplate2.tt以打断点的方式运行调试T4模板
然后就生成成功了
但是这里成功生成QS.Models类库下的所有类 我们只需要和数据相关的实体生成
在EF中 每个实体都有个特性TableAttribute来映射数据的表名 所以我们根据这个特性来判断是否应该生成文件
所以改动如下
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ Import Namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.ComponentModel.DataAnnotations.dll" #>
<#@ Import Namespace="System.ComponentModel.DataAnnotations.Schema" #>
<#@ output extension=".txt" #>
//这个必填 导入T4工具
<#@ include file="T4Toolbox.tt" #>
//这里填写bll模型的路径 当前TextTemplate2.tt目录下的Template文件夹里的BLLTemplate1.tt
<#@ include file="Template/BLLTemplate1.tt" #>
<#
//当前TextTemplate2.tt所在的模板路径
var currentPath = Path.GetDirectoryName(Host.TemplateFile);
//解决方案路径
string solutionPath = currentPath.Substring(0, currentPath.LastIndexOf("\\"));
//项目名称
string projectFullName = currentPath.Substring(currentPath.LastIndexOf("\\") + 1);
//实体文件所在路径
string modelFile = Path.Combine(solutionPath + @"\QS.Model\\bin\Debug\QS.Model.dll");
byte[] fileData = File.ReadAllBytes(modelFile);
Assembly assembly = Assembly.Load(fileData);
IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => !m.IsAbstract && m.IsClass && m.BaseType != null);
foreach (Type modelType in modelTypes)
{
object[] objAttrs = modelType.GetCustomAttributes(typeof(TableAttribute), true);
if(objAttrs.Length > 0){
//实例化bll模板
BLLTemplate bll= new BLLTemplate(modelType.Name);
string filePath= Path.Combine(currentPath,"bll", bll.FileName);
//创建文件
bll.RenderToFile(filePath);
}
}
#>
由于TableAttribute在命名空间System.ComponentModel.DataAnnotations.Schema所有需要导入该命名空间 但是导入该命名空间后还是报错 我就不知道是什么原因了 所以我就直接加载了这个dll
如果各位知道不妨告诉博主 博主将感激不尽
这样 生成代码就搞定了 所有的地方都可以用这样的方式生成
在视图里面我们需要字段来显示标签就可以这样
新建Index视图模型叫 IndexViewTemplate.tt
<#+
public class IndexViewTemplate : CSharpTemplate
{
string name;
private string[] parme;
private string[] description;
public IndexViewTemplate(string modelName,string[] parmes,string[] descriptions)
{
name = modelName;
parme = parmes;
description = descriptions;
}
/// <summary>
/// 获取 生成的文件名,根据模型名定义
/// </summary>
public string FileName
{
get
{
return string.Format("index.cshtml", EntityName);
}
}
/// <summary>
/// 实体名称
/// </summary>
public string EntityName
{
get
{
return name.Replace("Model", string.Empty);
}
}
public string View1{
get{
string parmes = null;
foreach(string item in description){
string newline = "\n";
if(item == description[description.Length-1])
newline = string.Empty;
parmes += $"<th style='text-align:center;'>{item}</th>{newline}";
}
return parmes;
}
}
public string List{
get{
string parmes = string.Empty;
for(int i=0;i<parme.Length;i++){
string newline = "\n";
if(i == parme.Length-1)
newline = string.Empty;
parmes += $"row.insertCell({i}).innerHTML = n.{parme[i]};{newline}";
}
return parmes;
}
}
public override string TransformText()
{
base.TransformText();
#>
@using LZH.BASE.Models;
@{
ViewBag.Title = "Index";
ViewBag.First = "<#=EntityName #>";
ViewBag.Second = "<#=EntityName #>";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@model <#=name#>
<div class="box box-primary">
<div class="box-header with-border">
<form class="form-inline">
<a href="/<#=EntityName #>/Add<#=EntityName #>/" class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-plus-sign"></span> 新增</a>
</form>
</div>
<div class="box-body" style="padding:0px">
<table data-toggle="table" id="table" style="border:none;width:100%;margin-bottom:50px; text-align:center;" cellpadding="0" cellspacing="0" class="list_table">
<thead>
<tr style="text-align:center;">
<#=View1 #>
</tr>
</thead>
<tbody id="listData"></tbody>
</table>
</div>
</div>
@section Js{
<script type="text/javascript">
$(document).ready(function () {
loadData();
});
//加载数据
function loadData() {
var load = layer.msg('数据加载中,请稍后', { icon: 16, time: 0, shade: [0.3, '#000'] });
var url = '@Url.Action("GetPageData")';
$.post(url, function (data) {
var table = $("#listData");
if (data.length > 0) {
$.each(data, function (index, n) {
var row = document.createElement('tr');
row.className = "tr";
<#=List #>
row.insertCell(4).innerHTML = "<a title='修改' class='btn btn-primary btn-xs' style='margin:0 3px' data-Id=" + n.Id + " οnclick='edit(this)'><span class='fa fa-edit'></span></a>" +
"<a title='删除' class='btn btn-warning btn-xs' style='margin:0 3px' data-Id=" + n.Id + " οnclick='delete1(this)'><span class=' fa fa-trash'></span></a>";
table.append(row);
});
tab();
}
layer.close(load);
});
}
function delete1(elemt) {
layer.confirm('确认删除该数据?', {
btn: ['确定', '放弃'] //按钮
}, function () {
var url = '@Url.Action("Delete<#=EntityName #>")';
var load = layer.msg('数据提交中,请稍后', { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post(url, { userId: $(elemt).data('id') }, function (data) {
if (data.Status == 0) {
layer.msg("删除成功!", { icon: 1, time: 1000, shade: [0.3, '#000'] }, function () {
window.location.href = "@Url.Action("Index")";
});
} else {
layer.msg(data.Message, { icon: 2, time: 1000, shade: [0.3, '#000'] });
}
});
});
}
function edit(elemt) {
window.location.href = "/<#=EntityName #>/Edit<#=EntityName #>/" + $(elemt).data('id');
}
</script>
}
<#+
return this.GenerationEnvironment.ToString();
}
}
#>
然后修改TextTemplate2.tt代码
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ Import Namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ Import Namespace="System.Collections.Generic" #>
<#@ import namespace="System.ComponentModel" #>
<#@ assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.ComponentModel.DataAnnotations.dll" #>
<#@ Import Namespace="System.ComponentModel.DataAnnotations.Schema" #>
<#@ output extension=".txt" #>
//这个必填 导入T4工具
<#@ include file="T4Toolbox.tt" #>
//这里填写bll模型的路径 当前TextTemplate2.tt目录下的Template文件夹里的BLLTemplate1.tt
<#@ include file="Template/IndexViewTemplate.tt" #>
<#
//当前TextTemplate2.tt所在的模板路径
var currentPath = Path.GetDirectoryName(Host.TemplateFile);
//解决方案路径
string solutionPath = currentPath.Substring(0, currentPath.LastIndexOf("\\"));
//项目名称
string projectFullName = currentPath.Substring(currentPath.LastIndexOf("\\") + 1);
//实体文件所在路径
string modelFile = Path.Combine(solutionPath + @"\QS.Model\\bin\Debug\QS.Model.dll");
byte[] fileData = File.ReadAllBytes(modelFile);
Assembly assembly = Assembly.Load(fileData);
IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => !m.IsAbstract && m.IsClass && m.BaseType != null);
foreach (Type modelType in modelTypes)
{
object[] objAttr = modelType.GetCustomAttributes(typeof(TableAttribute), true);
if(objAttr.Length > 0){
List<string> parmes = new List<string>();
List<string> description = new List<string>();
//获取公共参数
var pf = modelType.GetProperties();
foreach (PropertyInfo item in pf)
{
object[] objAttrs = item.GetCustomAttributes(typeof(NotMappedAttribute), true);
if (objAttrs.Length == 0)
{
parmes.Add(item.Name);
object[] objs = item.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (objs.Length == 0) //当描述属性没有时,直接返回名称
{
description.Add(item.Name);
}else{
DescriptionAttribute descriptionAttribute = (DescriptionAttribute)objs[0];
description.Add(descriptionAttribute.Description);
}
}
}
//创建index
string modelName = modelType.Name;
IndexViewTemplate indexTemplate = new IndexViewTemplate(modelName,parmes.ToArray(),description.ToArray());
var fileName = indexTemplate.FileName;
var indexFile = Path.Combine(currentPath,"ModelView",indexTemplate.EntityName, indexTemplate.FileName);
//判断指定文件夹下面是否创建过该文件
if(!File.Exists(indexFile)){
indexTemplate.RenderToFile(indexFile);
}
}
}
#>
好了这样就行了 增删改查视图都是一样的 不过要注意模板里面的FileName字段,这里的所有文件生成都是根据这个字段来的
如果你的实体dll有依赖的 引用的其他程序集 需要加载所有的依赖项才可以
具体参考:https://www.cnblogs.com/zagelover/articles/2726034.html
提个问题:生成需要反射的dll是出现该文件已锁定是怎么回事 我使用的File.ReadAllBytes()应该不会锁定该文件吧