我为我的应用程序开发了一个令人困惑的部分。
我正在使用名为“Allowed For”的自定义属性进行身份验证,然后使用用户类型。
例如,通过方法会有数据注释[Allowfor(UserType.Admin)]
,但我遇到的问题是我想在数据库中存储以下属性的UserTypes列表:
因此,在运行时甚至只需点击一个按钮,我想构建一个Enum类,其中包含未删除的枚举列表。
任何人都可以就我的方式提出一些建议,因为我似乎无法做到这一点,而且无法找到太多帮助谷歌搜索。
我只需知道以下事项:
答案 0 :(得分:1)
我做过与T4模板非常相似的事情。诀窍是知道需要哪些dll,找到它们等(例如,在Visual Studio 2013中,EnvDET被引用为“import namespace =”EnvDTE“而不是EvnDTE.dll
基本上你需要和他们一起玩,试着获得你想要的结果。在解决方案中创建一个T4项目,然后开始填写。
我使用命令对象(并且使用MySQL库来代替以下代码),但它应该让你知道我是如何运行它的。
<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".generated.cs" #>
<#@ Assembly Name="EnvDTE" #>
<#@ Assembly Name="System.Data" #>
<#@ Assembly Name="$(SolutionDir)Services.Entities\bin\DevTest\Libraries.DB.dll" #> **// * custom location for custom libraries**
<#@ Assembly Name="$(SolutionDir)Services.Entities\bin\DevTest\MySql.Data.dll" #> **// custom location for custom libraries**
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#
string tableName = "";
//string path = Path.GetDirectoryName(Host.TemplateFile);
string connectionString = "mysqlConnectionString"; **// replaced with regular value, could pull from web.config but it's only updated rarely**
// Get containing project
IServiceProvider serviceProvider = (IServiceProvider)Host;
DTE dte = (DTE)serviceProvider.GetService(typeof(DTE));
//Project project = dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
#>
using System;
using System.CodeDom.Compiler;
namespace Services.Entities
{
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum Store
{
<#
using (var cmd = new Libraries.DB.Mysql.Command(connectionString)) **//Custom libraries to open a disposable command object**
{
cmd.Clear();
cmd.AppendCmd("select id, storecode, StoreName \n");
cmd.AppendCmd("from stores \n");
var reader = cmd.ExecuteReader();
while(reader.Read())
{
int storeId = Convert.ToInt32(reader["id"]);
string storecode = reader["storecode"].ToString();
string description = reader["StoreName"].ToString();
#> //We now have the data, let's use it! The code in <#= gets populated #>**
[Libraries.Utils.Enums.Info(Code = "<#= storecode #>", Name = "<#= description #>")] <#= Sanitize(description) #> = <#= storeId #>,
<#
}
}
#>
}
}
//This is a method which takes a name like "Some Descripton" and Sanitizes it to Some_Description so it can be usable as an enum**
<#+
static string Sanitize(string token)
{
// Replace all invalid chars by underscores
token = Regex.Replace(token, @"[\W\b]", "_", RegexOptions.IgnoreCase);
// If it starts with a digit, prefix it with an underscore
token = Regex.Replace(token, @"^\d", @"_$0");
// Check for reserved words
// TODO: Clean this up and add other reserved words (keywords, etc)
if (token == "Url") token = "_Url";
return token;
}
#>
关于这些文件需要注意的关键是&lt; ##&gt;之间的所有内容是运行的代码,您可以在该代码中创建变量。要显示,就像ASP一样,&lt;#= variable#&gt;。
我不确定每次构建解决方案时是否自动构建这些文件,但这似乎是一个简单的构建脚本。要编译它们,在编辑时,请保存。您可以右键单击该文件,然后从上下文菜单中单击“运行自定义工具”。您将看到文件中的错误以及相关生成的文件进行检查。
顺便说一下,上面的内容可能会产生这样的结果:
using System;
using System.CodeDom.Compiler;
namespace Services.Entities
{
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum Store
{
[Libraries.Utils.Enums.Info(Code = "ST1", Name = "Store 1")] Store1 = 1,
[Libraries.Utils.Enums.Info(Code = "ST2", Name = "Store 2")] Store2 = 2,
}
}
顺便说一下,标签外部的所有内容(&lt;#,&lt;#=,&lt;#+)将作为输出发送给类。您需要确保在运行时正确设置了模板,否则您可能会因缺少括号等类而出现编译错误。