열거 형을 자동으로 생성 한 다음 데이터베이스 조회 테이블의 값을 기반으로 C #에서 해당 값을 사용하는 방법 (엔터프라이즈 라이브러리 데이터 레이어 사용)?
예를 들어, 데이터베이스에 새 조회 값을 추가하는 경우 코드에 추가 정적 열거 형 값 선언을 수동으로 추가 할 필요가 없습니다. 열거 형을 데이터베이스와 동기화 상태로 유지하고 싶습니다.
이것과 같은 것이 있습니까?
코드 생성 정적 열거 형 ( 코드 프로젝트 기사 Enum Code Generator-Generating enum code automatically from database look up tables에 따라 )을 생성하고 싶지 않으며 완전히 자동 인 것을 선호합니다.
답변
나는이 정확한 일을하고 있어요,하지만 당신은 해야 할 일이에 대한 코드 생성의 어떤 종류의 일을 할 수 있습니다.
내 솔루션에서 “EnumeratedTypes”프로젝트를 추가했습니다. 이것은 데이터베이스에서 모든 값을 가져 와서 열거 형을 구성하는 콘솔 애플리케이션입니다. 그런 다음 모든 열거 형을 어셈블리에 저장합니다.
열거 형 생성 코드는 다음과 같습니다.
// 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");
솔루션의 다른 프로젝트는이 생성 된 어셈블리를 참조합니다. 결과적으로 코드에서 인텔리 센스로 완성 된 동적 열거 형을 사용할 수 있습니다.
그런 다음이 “EnumeratedTypes”프로젝트가 빌드 된 후 자체적으로 실행되고 “MyEnums.dll”파일을 생성하도록 빌드 후 이벤트를 추가했습니다.
그건 그렇고, “EnumeratedTypes”가 먼저 빌드되도록 프로젝트 의 빌드 순서 를 변경하는 데 도움이됩니다 . 그렇지 않으면 동적으로 생성 된 .dll을 사용하기 시작하면 .dll이 삭제되면 빌드를 수행 할 수 없습니다. (닭고기와 달걀 종류의 문제-솔루션의 다른 프로젝트에서 제대로 빌드하려면이 .dll이 필요하며 솔루션을 빌드 할 때까지 .dll을 만들 수 없습니다 …)
이 msdn 기사 에서 위의 코드 대부분을 얻었습니다 .
도움이 되었기를 바랍니다!
답변
열거 형은 컴파일 타임에 지정해야합니다. 런타임 동안에는 열거 형을 동적으로 추가 할 수 없습니다. 왜 코드에서 열거 형에 대한 사용 / 참조가 없을까요?
Professional C # 2008에서 :
C #에서 열거 형의 진정한 힘은 배후에서 기본 클래스 인 System.Enum에서 파생 된 구조체로 인스턴스화된다는 것입니다. 이것은 유용한 작업을 수행하기 위해 그들에 대해 메서드를 호출 할 수 있음을 의미합니다. .NET Framework가 구현되는 방식으로 인해 열거 형을 구문 적으로 구조체로 처리하는 것과 관련된 성능 손실은 없습니다. 실제로 코드가 컴파일되면 enum은 int 및 float처럼 기본 유형으로 존재합니다.
따라서 원하는 방식으로 Enum을 사용할 수 있는지 잘 모르겠습니다.
답변
실제 열거 형이어야합니까? Dictionary<string,int>
대신 사용하는 것은 어떻습니까?
예를 들면
Dictionary<string, int> MyEnum = new Dictionary(){{"One", 1}, {"Two", 2}};
Console.WriteLine(MyEnum["One"]);
답변
T4 템플릿 으로이 작업을 수행했습니다 . .tt 파일을 프로젝트에 드롭하고 빌드 전 단계로 T4 템플릿을 실행하도록 Visual Studio를 설정하는 것은 매우 간단합니다.
T4는 .cs 파일을 생성하므로 데이터베이스를 쿼리하고 결과에서 .cs 파일에 열거 형을 만들 수 있습니다. 빌드 전 작업으로 연결되어 모든 빌드에서 열거 형을 다시 생성하거나 필요에 따라 T4를 수동으로 실행할 수 있습니다.
답변
DB에 다음이 있다고 가정 해 보겠습니다.
table enums
-----------------
| id | name |
-----------------
| 0 | MyEnum |
| 1 | YourEnum |
-----------------
table enum_values
----------------------------------
| id | enums_id | value | key |
----------------------------------
| 0 | 0 | 0 | Apple |
| 1 | 0 | 1 | Banana |
| 2 | 0 | 2 | Pear |
| 3 | 0 | 3 | Cherry |
| 4 | 1 | 0 | Red |
| 5 | 1 | 1 | Green |
| 6 | 1 | 2 | Yellow |
----------------------------------
필요한 값을 얻기 위해 선택을 구성하십시오.
select * from enums e inner join enum_values ev on ev.enums_id=e.id where e.id=0
열거 형에 대한 소스 코드를 생성하면 다음과 같은 결과를 얻을 수 있습니다.
String enumSourceCode = "enum " + enumName + "{" + enumKey1 + "=" enumValue1 + "," + enumKey2 + ... + "}";
(분명히 이것은 일종의 루프로 구성됩니다.)
그런 다음 재미있는 부분, 열거 형 컴파일 및 사용 :
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cs = new CompilerParameters();
cp.GenerateInMemory = True;
CompilerResult result = provider.CompileAssemblyFromSource(cp, enumSourceCode);
Type enumType = result.CompiledAssembly.GetType(enumName);
이제 유형이 컴파일되고 사용할 준비가되었습니다.
DB에 저장된 enum 값을 얻으려면 다음을 사용할 수 있습니다.
[Enum].Parse(enumType, value);
여기서 value는 정수 값 (0, 1 등) 또는 열거 형 텍스트 / 키 (Apple, Banana 등) 일 수 있습니다.
답변
Pandincus 의 답 을 “선반의”코드와 몇 가지 설명과 함께 보여 주기만하면됩니다.이 예제에는 두 가지 솔루션이 필요합니다 (하나를 통해 수행 할 수도 있음을 알고 있습니다;), 고급 학생들에게 발표하게하십시오.
따라서 다음은 테이블에 대한 DDL SQL입니다.
USE [ocms_dev]
GO
CREATE TABLE [dbo].[Role](
[RoleId] [int] IDENTITY(1,1) NOT NULL,
[RoleName] [varchar](50) NULL
) ON [PRIMARY]
다음은 dll을 생성하는 콘솔 프로그램입니다.
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
다음은 출력을 인쇄하는 콘솔 프로그래밍입니다 (dll을 참조해야 함). 고급 수강생이 모든 것을 하나의 솔루션에 동적 로딩과 결합하고 이미 빌드 dll이 있는지 확인하는 솔루션을 제시하게하십시오.
// 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
답변
우리가 잘못된 방향에서 오는 것 아닌가요?
배포 된 릴리스의 수명 동안 데이터가 전혀 변경 될 가능성이있는 경우 열거 형은 적절하지 않으며 사전, 해시 또는 기타 동적 컬렉션을 사용해야합니다.
배포 된 릴리스의 수명 동안 가능한 값 집합이 고정되어 있음을 알고있는 경우 열거 형을 사용하는 것이 좋습니다.
당신이 경우 해야한다 열거 세트를 복제 데이터베이스에 뭔가를 가지고, 왜 지우고 열거 값의 최종 세트로 데이터베이스 테이블을 다시 채울 수있는 배포 단계를 추가하지?