C# p>
T4生成一个.cs文件,这意味着您可以让它查询数据库并根据结果在.cs文件中构建一个枚举。作为预构建任务,它将在每次构建时重新创建您的枚举,或者您可以根据需要手动运行T4。我总是喜欢编写自己的“自定义枚举”。我有一个稍微复杂一点的类,但我可以重用它:C# p>,c#,database,dynamic,enums,C#,Database,Dynamic,Enums,T4生成一个.cs文件,这意味着您可以让它查询数据库并根据结果在.cs文件中构建一个枚举。作为预构建任务,它将在每次构建时重新创建您的枚举,或者您可以根据需要手动运行T4。我总是喜欢编写自己的“自定义枚举”。我有一个稍微复杂一点的类,但我可以重用它: 公共抽象类CustomEnum { 私有只读字符串\u名称; 私有只读对象_id; 受保护的CustomEnum(字符串名称、对象id) { _名称=名称; _id=id; } 公共字符串名 { 获取{return\u name;} } 公共对象I
公共抽象类CustomEnum
{
私有只读字符串\u名称;
私有只读对象_id;
受保护的CustomEnum(字符串名称、对象id)
{
_名称=名称;
_id=id;
}
公共字符串名
{
获取{return\u name;}
}
公共对象Id
{
获取{return\u id;}
}
公共重写字符串ToString()
{
返回_name;
}
}
公共抽象类CustomEnum:CustomEnum
其中TEnumType:CustomEnum
{
受保护的CustomEnum(字符串名称、类型id)
:base(名称、id)
{ }
公共新类型Id
{
获取{return(TIdType)base.Id;}
}
公共静态TEnumType FromName(字符串名称)
{
尝试
{
从委托返回(entry=>entry.Name.Equals(Name));
}
捕获(异常ae)
{
抛出新的ArgumentException(“自定义枚举的非法名称’”+typeof(TEnumType).name+“”,ae);
}
}
公共静态TEnumType FromId(TIdType id)
{
尝试
{
从委托返回(entry=>entry.Id.Equals(Id));
}
捕获(异常ae)
{
抛出新的ArgumentException(“自定义枚举的非法id'”+typeof(TEnumType).Name+“'”,ae);
}
}
公共静态IEnumerable GetAll()
{
var元素=新集合();
var infoArray=typeof(TEnumType).GetFields(BindingFlags.Public | BindingFlags.Static);
foreach(infoArray中的var信息)
{
var type=info.GetValue(null)作为TEnumType;
元素。添加(类型);
}
返回元素;
}
受保护的静态TEnumType FromDelegate(谓词)
{
if(谓词==null)
抛出新的ArgumentNullException(“谓词”);
foreach(GetAll()中的var条目)
{
if(谓词(条目))
返回条目;
}
抛出新ArgumentException(“使用谓词时未找到元素”);
}
}
现在,我只需要创建我要使用的枚举:
公共密封类样本枚举:CustomEnum
{
public static readonly SampleEnum Element1=新的SampleEnum(“Element1”,1,“foo”);
public static readonly SampleEnum Element2=新的SampleEnum(“Element2”,2,“bar”);
私有SampleEnum(字符串名称、整数id、字符串附加文本)
:base(名称、id)
{
AdditionalText=AdditionalText;
}
公共字符串附加文本{get;private set;}
}
最后,我可以随心所欲地使用它:
static void Main(字符串[]args)
{
foreach(SampleEnum.GetAll()中的var元素)
{
WriteLine(“{0}:{1}”,元素,元素.AdditionalText);
WriteLine(“Is'Element2':{0}”,element==SampleEnum.Element2);
Console.WriteLine();
}
Console.ReadKey();
}
我的输出是:
Element1:foo
是'Element2':False
元素2:酒吧
“Element2”是否为True
保留枚举并同时创建动态值列表的一种方法是将当前拥有的枚举与动态创建的字典一起使用
由于大多数枚举是在定义要使用的上下文中使用的,并且“动态枚举”将由动态进程支持,因此您可以区分这两种类型
第一步是创建一个表/集合,其中包含动态条目的ID和引用。在表中,您将自动增加比最大枚举值大得多的值
现在是动态枚举部分,我假设您将使用枚举创建一组应用一组规则的条件,其中一些是动态生成的
Get integer from database
If Integer is in Enum -> create Enum -> then run Enum parts
If Integer is not a Enum -> create Dictionary from Table -> then run Dictionary parts.
我们不是走错方向了吗 如果数据可能在已部署版本的生命周期内发生任何更改,那么枚举就是不合适的,您需要使用字典、哈希或其他动态集合 如果您知道可能的值集在部署的版本的生命周期内是固定的,那么最好使用枚举 如果您的数据库中必须有复制枚举集的内容,那么为什么不添加一个部署步骤来清除数据库表并用最终的枚举值集重新填充它呢?enum builder类
public class XEnum
{
private EnumBuilder enumBuilder;
private int index;
private AssemblyBuilder _ab;
private AssemblyName _name;
public XEnum(string enumname)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
_name = new AssemblyName("MyAssembly");
_ab = currentDomain.DefineDynamicAssembly(
_name, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = _ab.DefineDynamicModule("MyModule");
enumBuilder = mb.DefineEnum(enumname, TypeAttributes.Public, typeof(int));
}
/// <summary>
/// adding one string to enum
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public FieldBuilder add(string s)
{
FieldBuilder f = enumBuilder.DefineLiteral(s, index);
index++;
return f;
}
/// <summary>
/// adding array to enum
/// </summary>
/// <param name="s"></param>
public void addRange(string[] s)
{
for (int i = 0; i < s.Length; i++)
{
enumBuilder.DefineLiteral(s[i], i);
}
}
/// <summary>
/// getting index 0
/// </summary>
/// <returns></returns>
public object getEnum()
{
Type finished = enumBuilder.CreateType();
_ab.Save(_name.Name + ".dll");
Object o1 = Enum.Parse(finished, "0");
return o1;
}
/// <summary>
/// getting with index
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public object getEnum(int i)
{
Type finished = enumBuilder.CreateType();
_ab.Save(_name.Name + ".dll");
Object o1 = Enum.Parse(finished, i.ToString());
return o1;
}
}
话又说回来,我也厌倦了根据Id/Name数据库表列写出枚举,复制和粘贴SSMS中查询的内容 下面是一个超级脏存储过程,它以表名、要用于c#枚举名的列名和要用于c#枚举值的列名作为输入 我使用的大多数表名a)以“s”结尾b)有一个[TABLENAME]Id列,c)有一个[TABLENAME]Name列,因此有几个if语句将采用这种结构,在这种情况下,不需要列名参数 这些例子的一点上下文——“Stonk”在这里并不是真正的意思是“stock”,但我使用“Stonk”的方式是指“在一段时间内有一些数字与之关联的事物”,但这并不重要,它只是一个具有此Id/名称模式的表的示例。看起来是这样的:
// Get the current application domain for the current thread
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName name = new AssemblyName("MyEnums");
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name,
AssemblyBuilderAccess.RunAndSave);
// Define a dynamic module in "MyEnums" assembly.
// For a single-module assembly, the module has the same name as the assembly.
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name,
name.Name + ".dll");
// Define a public enumeration with the name "MyEnum" and an underlying type of Integer.
EnumBuilder myEnum = moduleBuilder.DefineEnum("EnumeratedTypes.MyEnum",
TypeAttributes.Public, typeof(int));
// Get data from database
MyDataAdapter someAdapter = new MyDataAdapter();
MyDataSet.MyDataTable myData = myDataAdapter.GetMyData();
foreach (MyDataSet.MyDataRow row in myData.Rows)
{
myEnum.DefineLiteral(row.Name, row.Key);
}
// Create the enum
myEnum.CreateType();
// Finally, save the assembly
assemblyBuilder.Save(name.Name + ".dll");
CREATE TABLE StonkTypes (
StonkTypeId TINYINT IDENTITY(1,1) PRIMARY KEY NOT NULL,
StonkTypeName VARCHAR(200) NOT NULL CONSTRAINT UQ_StonkTypes_StonkTypeName UNIQUE (StonkTypeName)
)
创建proc后,此语句:
EXEC CreateCSharpEnum'StonkTypes'
选择此字符串:
public enum StonkTypes { Stonk = 1, Bond = 2, Index = 3, Fund = 4, Commodity = 5,
PutCallRatio = 6, }
我可以将其复制并粘贴到C#文件中
[Enum].Parse(enumType, value);
// Get the current application domain for the current thread
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName name = new AssemblyName("MyEnums");
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name,
AssemblyBuilderAccess.RunAndSave);
// Define a dynamic module in "MyEnums" assembly.
// For a single-module assembly, the module has the same name as the assembly.
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name,
name.Name + ".dll");
// Define a public enumeration with the name "MyEnum" and an underlying type of Integer.
EnumBuilder myEnum = moduleBuilder.DefineEnum("EnumeratedTypes.MyEnum",
TypeAttributes.Public, typeof(int));
// Get data from database
MyDataAdapter someAdapter = new MyDataAdapter();
MyDataSet.MyDataTable myData = myDataAdapter.GetMyData();
foreach (MyDataSet.MyDataRow row in myData.Rows)
{
myEnum.DefineLiteral(row.Name, row.Key);
}
// Create the enum
myEnum.CreateType();
// Finally, save the assembly
assemblyBuilder.Save(name.Name + ".dll");
USE [ocms_dev]
GO
CREATE TABLE [dbo].[Role](
[RoleId] [int] IDENTITY(1,1) NOT NULL,
[RoleName] [varchar](50) NULL
) ON [PRIMARY]
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.Data.Common;
using System.Data;
using System.Data.SqlClient;
namespace DynamicEnums
{
class EnumCreator
{
// after running for first time rename this method to Main1
static void Main ()
{
string strAssemblyName = "MyEnums";
bool flagFileExists = System.IO.File.Exists (
AppDomain.CurrentDomain.SetupInformation.ApplicationBase +
strAssemblyName + ".dll"
);
// Get the current application domain for the current thread
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName name = new AssemblyName ( strAssemblyName );
AssemblyBuilder assemblyBuilder =
currentDomain.DefineDynamicAssembly ( name,
AssemblyBuilderAccess.RunAndSave );
// Define a dynamic module in "MyEnums" assembly.
// For a single-module assembly, the module has the same name as
// the assembly.
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule (
name.Name, name.Name + ".dll" );
// Define a public enumeration with the name "MyEnum" and
// an underlying type of Integer.
EnumBuilder myEnum = moduleBuilder.DefineEnum (
"EnumeratedTypes.MyEnum",
TypeAttributes.Public,
typeof ( int )
);
#region GetTheDataFromTheDatabase
DataTable tableData = new DataTable ( "enumSourceDataTable" );
string connectionString = "Integrated Security=SSPI;Persist " +
"Security Info=False;Initial Catalog=ocms_dev;Data " +
"Source=ysg";
using (SqlConnection connection =
new SqlConnection ( connectionString ))
{
SqlCommand command = connection.CreateCommand ();
command.CommandText = string.Format ( "SELECT [RoleId], " +
"[RoleName] FROM [ocms_dev].[dbo].[Role]" );
Console.WriteLine ( "command.CommandText is " +
command.CommandText );
connection.Open ();
tableData.Load ( command.ExecuteReader (
CommandBehavior.CloseConnection
) );
} //eof using
foreach (DataRow dr in tableData.Rows)
{
myEnum.DefineLiteral ( dr[1].ToString (),
Convert.ToInt32 ( dr[0].ToString () ) );
}
#endregion GetTheDataFromTheDatabase
// Create the enum
myEnum.CreateType ();
// Finally, save the assembly
assemblyBuilder.Save ( name.Name + ".dll" );
} //eof Main
} //eof Program
} //eof namespace
// add the reference to the newly generated dll
use MyEnums ;
class Program
{
static void Main ()
{
Array values = Enum.GetValues ( typeof ( EnumeratedTypes.MyEnum ) );
foreach (EnumeratedTypes.MyEnum val in values)
{
Console.WriteLine ( String.Format ( "{0}: {1}",
Enum.GetName ( typeof ( EnumeratedTypes.MyEnum ), val ),
val ) );
}
Console.WriteLine ( "Hit enter to exit " );
Console.ReadLine ();
} //eof Main
} //eof Program
Get integer from database
If Integer is in Enum -> create Enum -> then run Enum parts
If Integer is not a Enum -> create Dictionary from Table -> then run Dictionary parts.
public class XEnum
{
private EnumBuilder enumBuilder;
private int index;
private AssemblyBuilder _ab;
private AssemblyName _name;
public XEnum(string enumname)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
_name = new AssemblyName("MyAssembly");
_ab = currentDomain.DefineDynamicAssembly(
_name, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = _ab.DefineDynamicModule("MyModule");
enumBuilder = mb.DefineEnum(enumname, TypeAttributes.Public, typeof(int));
}
/// <summary>
/// adding one string to enum
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public FieldBuilder add(string s)
{
FieldBuilder f = enumBuilder.DefineLiteral(s, index);
index++;
return f;
}
/// <summary>
/// adding array to enum
/// </summary>
/// <param name="s"></param>
public void addRange(string[] s)
{
for (int i = 0; i < s.Length; i++)
{
enumBuilder.DefineLiteral(s[i], i);
}
}
/// <summary>
/// getting index 0
/// </summary>
/// <returns></returns>
public object getEnum()
{
Type finished = enumBuilder.CreateType();
_ab.Save(_name.Name + ".dll");
Object o1 = Enum.Parse(finished, "0");
return o1;
}
/// <summary>
/// getting with index
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public object getEnum(int i)
{
Type finished = enumBuilder.CreateType();
_ab.Save(_name.Name + ".dll");
Object o1 = Enum.Parse(finished, i.ToString());
return o1;
}
}
string[] types = { "String", "Boolean", "Int32", "Enum", "Point", "Thickness", "long", "float" };
XEnum xe = new XEnum("Enum");
xe.addRange(types);
return xe.getEnum();
CREATE TABLE StonkTypes (
StonkTypeId TINYINT IDENTITY(1,1) PRIMARY KEY NOT NULL,
StonkTypeName VARCHAR(200) NOT NULL CONSTRAINT UQ_StonkTypes_StonkTypeName UNIQUE (StonkTypeName)
)
public enum StonkTypes { Stonk = 1, Bond = 2, Index = 3, Fund = 4, Commodity = 5,
PutCallRatio = 6, }
EXEC CreateCSharpEnum 'Stonks'
EXEC CreateCSharpEnum 'Stonks', 'Symbol'
CREATE OR ALTER PROCEDURE CreateCSharpEnum
@TableName VARCHAR(MAX),
@EnumNameColumnName VARCHAR(MAX) = NULL,
@EnumValueColumnName VARCHAR(MAX) = NULL
AS
DECLARE @LastCharOfTableName VARCHAR(1)
SELECT @LastCharOfTableName = RIGHT(@TableName, 1)
PRINT 'Last char = [' + @LastCharOfTableName + ']'
DECLARE @TableNameWithoutS VARCHAR(MAX)
IF UPPER(@LastCharOfTableName) = 'S'
SET @TableNameWithoutS = LEFT(@TableName, LEN(@TableName) - 1)
ELSE
SET @TableNameWithoutS = @TableName
PRINT 'Table name without trailing s = [' + @TableNameWithoutS + ']'
IF @EnumNameColumnName IS NULL
BEGIN
SET @EnumNameColumnName = @TableNameWithoutS + 'Name'
END
PRINT 'name col name = [' + @EnumNameColumnName + ']'
IF @EnumValueColumnName IS NULL
SET @EnumValueColumnName = @TableNameWithoutS + 'Id'
PRINT 'value col name = [' + @EnumValueColumnName + ']'
-- replace spaces and punctuation
SET @EnumNameColumnName = 'REPLACE(' + @EnumNameColumnName + ', '' '', '''')'
SET @EnumNameColumnName = 'REPLACE(' + @EnumNameColumnName + ', ''&'', '''')'
SET @EnumNameColumnName = 'REPLACE(' + @EnumNameColumnName + ', ''.'', '''')'
SET @EnumNameColumnName = 'REPLACE(' + @EnumNameColumnName + ', ''('', '''')'
SET @EnumNameColumnName = 'REPLACE(' + @EnumNameColumnName + ', '')'', '''')'
PRINT 'name col name with replace sql = [' + @EnumNameColumnName + ']'
DECLARE @SqlStr VARCHAR(MAX) = 'SELECT ' + @EnumNameColumnName
+ ' + '' = '''
+ ' + LTRIM(RTRIM(STR(' + @EnumValueColumnName + '))) + '','' FROM ' + @TableName + ' ORDER BY ' + @EnumValueColumnName
PRINT 'sql that gets rows for enum body = [' + @SqlStr + ']'
CREATE TABLE #EnumRowsTemp (s VARCHAR(MAX))
INSERT
INTO #EnumRowsTemp
EXEC(@SqlStr)
--SELECT * FROM #EnumRowsTemp
DECLARE @csharpenumbody VARCHAR(MAX)
SELECT @csharpenumbody = COALESCE(@csharpenumbody + ' ', '') + s FROM #EnumRowsTemp
--PRINT @csharpenumbody
DECLARE @csharpenum VARCHAR(MAX) = 'public enum ' + @TableName + ' { ' + @csharpenumbody + ' }'
PRINT @csharpenum
SELECT @csharpenum
DROP TABLE #EnumRowsTemp