动态枚举来自数据库表






4.82/5 (10投票s)
创建一个包含在数据库中定义的枚举的程序集。
引言
通过使用本文中提供的代码,您的应用程序可以轻松生成动态枚举。
背景
数据库应用程序编程的一个重要部分是识别和使用查找项,这些查找项在功能上类似于常量。在 .NET 之前,开发人员可以在数据库表中定义查找值,但为了在应用程序中将它们用作常量,他们需要一个单独的步骤,以 CONST
值或枚举的形式在应用程序中定义它们。这有时会带来问题 - 如何确保数据库值与应用程序值保持同步。使用 EnumBuilder
类和应用程序中的几行代码,所有这些都可以在您无需任何干预的情况下实现。
Using the Code
首先,在您的代码中设置对 System.Reflection.Emit
的引用。
Imports System.Reflection.Emit
下面的代码非常简单易用。只需在代码开始时将一些变量设置为您的值即可。此代码将创建一个新的程序集,由 assemblyName
变量指定,带有 DLL 扩展名,位于应用程序文件夹中。
OpenDatabase() 'you provide this
Try
Dim assemblyName As String = "DynEnum"
Dim lookupSQL As String = "SELECT ID, Name FROM AllMessageTypes"
Dim nameField As String = "Name"
Dim valueField As String = "ID"
Dim enumerationName As String = "MessageTypes"
Dim currentDomain As AppDomain = AppDomain.CurrentDomain
Dim aName As AssemblyName = New AssemblyName(assemblyName)
Dim ab As AssemblyBuilder = _
currentDomain.DefineDynamicAssembly(aName, _
AssemblyBuilderAccess.RunAndSave)
Dim mb As ModuleBuilder = ab.DefineDynamicModule(aName.Name, _
aName.Name & ".dll")
Dim eb As EnumBuilder = mb.DefineEnum(enumerationName, _
TypeAttributes.Public, GetType(Integer))
'your saved connection
Dim cmd As New SqlCommand(lookupSQL, _Connection)
Dim dr As SqlDataReader = cmd.ExecuteReader
If dr.HasRows Then
Do While dr.Read
eb.DefineLiteral(dr.GetValue(dr.GetOrdinal(nameField)), _
dr.GetValue(dr.GetOrdinal(valueField)))
Loop
End If
dr.Close()
eb.CreateType()
ab.Save(aName.Name & ".dll")
Catch ex As Exception
Throw ex
End Try
从这一点开始,您只需在运行一次应用程序并创建生成的 DLL 后,将 DLL 添加到应用程序的引用即可。如果您在查找表中添加或删除任何值,它会自动反映在枚举中,因为它是由应用程序生成的。
我将此代码放在将使用枚举的类的构造函数中,尽管我不认为它与应用程序的其余部分相关。如果您发现情况并非如此,请告诉我。
此方法可能存在的问题
我尚未验证这一点,但在应用程序执行期间,防病毒应用程序可能会将 DLL 中的更改视为受感染的文件,因此您可能需要注意这种情况。
关注点
有趣的是,即使您在应用程序中引用了新创建的 DLL,当应用程序运行并重新生成 DLL 时,也不会引发文件正在使用异常。我本以为会是这种情况,但它直接通过代码并创建新的 DLL。如果有人能向我解释这一点,我将不胜感激。此外,如果您在表中放置一个新值并运行您的应用程序,则新值会立即提供给应用程序。当然,在您停止应用程序之前,新值对 Visual Studio 的智能感知不可用。
更新:我想我已经确定了为什么在重新生成 DLL 时没有收到文件正在使用错误。据我了解,.NET DLL 实际上直到使用时才加载。在这种情况下,只要在重新生成之前没有使用过我们的动态 DLL,它就会被重新生成。因此,如果在重新生成代码之前,应用程序中的任何其他类都没有使用正在生成的枚举,我们的 DLL 将使用插入表中的任何新值重新生成。但不幸的是,这也意味着我们不能在发生重新生成的类中拥有我们枚举类型的 Private
、Friend
、Protected
或 Public
变量,因为这些变量是在运行类构造函数代码之前初始化的。所以请注意您正在创建的枚举变量的作用域,否则您将收到文件正在使用异常。
历史
- 原始提交 - 2008 年 11 月 14 日,星期五
- 更新 - 2008 年 11 月 19 日,星期三