สร้าง Enum โดยอัตโนมัติตามค่าในตารางการค้นหาฐานข้อมูลหรือไม่


116

ฉันจะสร้าง enum โดยอัตโนมัติแล้วใช้ค่าใน C # ตามค่าในตารางการค้นหาฐานข้อมูลได้อย่างไร (โดยใช้ชั้นข้อมูลไลบรารีขององค์กร)

ตัวอย่างเช่นถ้าฉันเพิ่มค่าการค้นหาใหม่ในฐานข้อมูลฉันไม่ต้องการที่จะต้องเพิ่มการประกาศค่า enum แบบคงที่พิเศษในโค้ดด้วยตนเอง - ฉันต้องการให้ enum ซิงค์กับฐานข้อมูล

มีแบบนี้ด้วยเหรอ?


ฉันไม่ต้องการสร้างโค้ดที่สร้างแบบคงที่ enum (ตามบทความThe Code Project Enum Code Generator - การสร้างโค้ด enum โดยอัตโนมัติจากตารางค้นหาฐานข้อมูล ) และต้องการให้เป็นแบบอัตโนมัติโดยสมบูรณ์


เป็นไปได้ไหมที่คุณกำลังพยายามใช้การแจงนับในทางที่มีทางออกที่ดีกว่า
ด่าน

ฉันกับ @ แดนต้องมีวิธีที่ดีกว่านี้
N_A

@mydogisbox จะมีวิธีไหนดีกว่ากัน?
eran otzap

@eranotzer อันที่จริงหลังจากคิดถึงเรื่องนี้สักหน่อยมันจะค่อนข้างง่ายที่จะเขียนขั้นตอนก่อนสร้างที่ค้นหาฐานข้อมูลและสร้าง enum จากมัน
N_A

1
ตามที่กล่าวไว้ฉันไม่แน่ใจว่าเขาหมายถึงอะไรโดย "ฉันไม่ต้องการสร้างรหัสที่สร้างคงที่" ดังนั้นอาจจะไม่ตรงกับความต้องการ
N_A

คำตอบ:


97

ฉันกำลังทำสิ่งนี้อยู่ แต่คุณต้องสร้างรหัสบางอย่างเพื่อให้สิ่งนี้ใช้งานได้

ในโซลูชันของฉันฉันได้เพิ่มโปรเจ็กต์ "EnumeratedTypes" นี่คือแอปพลิเคชันคอนโซลที่รับค่าทั้งหมดจากฐานข้อมูลและสร้าง enums จากค่าเหล่านี้ จากนั้นจะบันทึก enums ทั้งหมดลงในแอสเซมบลี

รหัสการสร้าง enum เป็นดังนี้:

// 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");

โครงการอื่น ๆ ของฉันในโซลูชันอ้างอิงแอสเซมบลีที่สร้างขึ้นนี้ ด้วยเหตุนี้ฉันจึงสามารถใช้ไดนามิก enums ในโค้ดพร้อมด้วย intellisense

จากนั้นฉันจึงเพิ่มเหตุการณ์หลังการสร้างเพื่อที่หลังจากสร้างโปรเจ็กต์ "EnumeratedTypes" นี้มันจะรันเองและสร้างไฟล์ "MyEnums.dll"

โดยวิธีนี้จะช่วยในการเปลี่ยนลำดับการสร้างของโครงการของคุณเพื่อให้ "EnumeratedTypes" ถูกสร้างขึ้นก่อน มิฉะนั้นเมื่อคุณเริ่มใช้. dll ที่สร้างขึ้นแบบไดนามิกคุณจะไม่สามารถสร้างบิลด์ได้หาก. dll เคยถูกลบไป (ปัญหาประเภทไก่และไข่ - โครงการอื่น ๆ ของคุณในโซลูชันนี้ต้องการ. dll นี้เพื่อสร้างอย่างถูกต้องและคุณไม่สามารถสร้าง. dll ได้จนกว่าคุณจะสร้างโซลูชันของคุณ ... )

ฉันได้มากที่สุดของรหัสดังกล่าวจากบทความนี้ MSDN

หวังว่านี่จะช่วยได้!


7
สำหรับผู้ที่ไม่ทราบวิธีเรียกใช้ไฟล์ปฏิบัติการที่เป็นผลลัพธ์ในภายหลังการสร้าง: 1) คลิกขวาที่โครงการ 2) คลิกที่คุณสมบัติ 3) คลิกที่สร้างเหตุการณ์ 4) ในกล่องข้อความ "บรรทัดคำสั่งเหตุการณ์หลังการสร้าง" $ (TargetPath)
มิเกล

มันเป็นไปได้ที่จะทำแบบไดนามิกที่มีความหมาย Enum แอตทริบิวต์ที่กำหนดเองเป็นที่กล่าวถึงในเรื่องนี้การเชื่อมโยง ?
Balagurunathan Marimuthu

49

ต้องระบุ Enums ในเวลาคอมไพล์คุณไม่สามารถเพิ่ม enums แบบไดนามิกระหว่างรันไทม์ได้และทำไมคุณถึงไม่มีการใช้ / การอ้างอิงในโค้ด?

จาก Professional C # 2008:

พลังที่แท้จริงของ enum ใน C # คือเบื้องหลังพวกมันถูกสร้างอินสแตนซ์เป็นโครงสร้างที่มาจากคลาสฐาน System.Enum ซึ่งหมายความว่าเป็นไปได้ที่จะเรียกวิธีการต่อต้านพวกเขาเพื่อทำงานที่มีประโยชน์ โปรดสังเกตว่าเนื่องจากวิธีการนำ. NET Framework ไปใช้งานจึงไม่มีการสูญเสียประสิทธิภาพที่เกี่ยวข้องกับการจัดการ enums ในเชิงไวยากรณ์เป็นโครงสร้าง ในทางปฏิบัติเมื่อคอมไพล์โค้ดของคุณ enums จะมีอยู่เป็นประเภทดั้งเดิมเช่นเดียวกับ int และ float

ดังนั้นฉันไม่แน่ใจว่าคุณสามารถใช้ Enums ในแบบที่คุณต้องการได้


1
ไม่แน่ใจว่าเหตุผลของ billfredtom คืออะไร แต่ของฉันคือฉันสามารถหลีกเลี่ยงการค้นหาสตริงด้วยตนเองสำหรับบางคีย์แทนการสร้างไว้ในรหัสของฉัน ฉันแค่ชอบที่จะสามารถใช้ตรรกะกับค่าที่พิมพ์หนักแน่นแทนสตริงที่อ่อนแอ ข้อแม้คือเนื่องจากตอนนี้เรามีโค้ดที่อาศัย Enum ที่สร้างขึ้นแบบไดนามิกหากเราลบค่าออกจากฐานข้อมูลในครั้งต่อไปที่เราพยายามรวบรวมโค้ดของเรามันจะล้มเหลว
Pandincus

14
โปสเตอร์และผู้โหวต 18 คนพลาดประเด็นของเขาไป ดูเหมือนว่าเขาต้องการสร้าง enums ไม่ใช่รันไทม์ไดนามิก enums
Matt Mitchell

+1 enum เป็นอีกวิธีหนึ่งในการกำหนดค่าคงที่ของจำนวนเต็ม (แม้ว่าจะSystem.Enumมีฟังก์ชันเพิ่มเติมบางอย่างก็ตาม) แทนการเขียนที่คุณเขียนconst int Red=0, Green=1, Blue=3; enum { Red, Green, Blue }ค่าคงที่เป็นค่าคงที่นิยามไม่ใช่ไดนามิก
Olivier Jacot-Descombes

2
@ โอลิเวอร์หากคุณต้องการโต้แย้งความหมายใช่คุณถูกต้อง แต่ฉันเห็นด้วยกับความคิดเห็นของ Graphain - ฉันเชื่อว่า OP กำลังมองหาenums ที่สร้างขึ้น เขาต้องการให้ค่า enum มาจากฐานข้อมูลและไม่ต้องฮาร์ดโค้ด
Pandincus

1
หรือ ... สมมติว่าฉันอนุญาตให้ใครบางคนใน web.config ของฉันกำหนดประเภทโทเค็นสำหรับเทมเพลตอีเมลสำหรับรหัสเทมเพลตอีเมลของฉัน คงจะดีถ้า enum ที่มีอยู่ของฉันชื่อว่า EmailTokens ซึ่งแสดงถึงประเภทสตริงเหล่านั้นจะถูกสร้างขึ้นตามประเภทที่กำหนดไว้ใน web.config ของฉัน ดังนั้นหากใครเพิ่มโทเค็นอีเมลใหม่ใน webconfig ผ่านค่าคีย์ของฉันเช่น "Email, FName" และฉันมี enum อยู่แล้วซึ่งฉันจะใช้แทนโทเค็นเหล่านี้เช่น EmailTemplate อีเมลคงจะดีถ้าใคร ๆ ก็ทำได้ เพิ่มโทเค็นสตริงใหม่ในคีย์นั้นใน web.config และ enum ของฉันจะเพิ่ม const โดยอัตโนมัติ
PositiveGuy

18

มันต้องเป็น enum จริงหรือ? วิธีการใช้Dictionary<string,int>แทน?

ตัวอย่างเช่น

Dictionary<string, int> MyEnum = new Dictionary(){{"One", 1}, {"Two", 2}};
Console.WriteLine(MyEnum["One"]);

11
ฉันจะไม่ลองทำแบบนี้ คุณสูญเสียการตรวจสอบเวลารวบรวมและมีแนวโน้มที่จะพิมพ์ผิดพลาด ประโยชน์ทั้งหมดของ enums หายไป คุณสามารถแนะนำค่าคงที่ของสตริงได้ แต่คุณกลับมาที่จุดเริ่มต้น
Daniel Brückner

1
ฉันเห็นด้วย. แต่อย่าลืมว่าสตริงที่พิมพ์ผิดจะถูกจับที่รันไทม์ เพียงเพิ่มกรณีทดสอบเพื่อให้ครอบคลุมสมาชิก enum ทั้งหมด
Autodidact

1
การพิมพ์ผิดไม่ใช่ปัญหาหากคุณใช้ค่าคงที่แทนตัวอักษร
Maslow

@ Maslow สมมติว่าคุณหมายถึง enums ไม่ใช่ค่าคงที่ของสตริง
Matt Mitchell

4
+1 การใช้พจนานุกรมหรือ HashSet ใกล้เคียงที่สุดกับสิ่งที่อาจเป็นไดนามิกเอนัม ไดนามิกเต็มที่หมายความว่ามันเกิดขึ้นที่รันไทม์ดังนั้นการตรวจสอบข้อผิดพลาดจะต้องเกิดขึ้นที่รันไทม์
Olivier Jacot-Descombes

14

ฉันทำสิ่งนี้กับเทมเพลตT4แล้ว การวางไฟล์. tt ลงในโครงการของคุณเป็นเรื่องเล็กน้อยและตั้งค่า Visual Studio เพื่อเรียกใช้เทมเพลต T4 เป็นขั้นตอนก่อนสร้าง

T4 สร้างไฟล์. cs ซึ่งหมายความว่าคุณสามารถมีได้เพียงแค่สอบถามฐานข้อมูลและสร้าง enum ในไฟล์. cs จากผลลัพธ์ ต่อสายเป็นงานก่อนสร้างมันจะสร้าง enum ของคุณขึ้นมาใหม่ในทุกบิลด์หรือคุณสามารถรัน T4 ด้วยตนเองได้ตามต้องการแทน


12

สมมติว่าคุณมีสิ่งต่อไปนี้ในฐานข้อมูลของคุณ:

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

สร้างซอร์สโค้ดสำหรับ enum และคุณจะได้รับสิ่งต่อไปนี้:

String enumSourceCode = "enum " + enumName + "{" + enumKey1 + "=" enumValue1 + "," + enumKey2 + ... + "}";

(เห็นได้ชัดว่าสิ่งนี้ถูกสร้างขึ้นในลักษณะวนซ้ำ)

จากนั้นก็มาถึงส่วนที่สนุกสนานรวบรวม enum ของคุณและใช้มัน:

CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cs = new CompilerParameters();
cp.GenerateInMemory = True;

CompilerResult result = provider.CompileAssemblyFromSource(cp, enumSourceCode);

Type enumType = result.CompiledAssembly.GetType(enumName);

ตอนนี้คุณมีประเภทที่รวบรวมและพร้อมใช้งานแล้ว
ในการรับค่า enum ที่เก็บไว้ในฐานข้อมูลคุณสามารถใช้:

[Enum].Parse(enumType, value);

โดยที่ค่าอาจเป็นค่าจำนวนเต็ม (0, 1 เป็นต้น) หรือข้อความ / คีย์ enum (Apple, Banana ฯลฯ )


4
สิ่งนี้จะช่วยได้จริงในทางใด? ไม่มีประเภทความปลอดภัยและไม่มี intellisense โดยพื้นฐานแล้วมันเป็นเพียงวิธีที่ซับซ้อนกว่าในการใช้ค่าคงที่เนื่องจากเขาต้องให้ค่าอยู่แล้ว
Runeborg

2
Sani - สมบูรณ์แบบ! นี่คือสิ่งที่ฉันต้องการ สำหรับผู้ที่ตั้งคำถามเกี่ยวกับเหตุผลเช่นนี้ฉันกำลังใช้ไลบรารีของผู้ขายที่ต้องการให้คุณสมบัติตั้งเป็นชื่อของการแจงนับ การแจงนับ จำกัด ช่วงค่าที่ถูกต้องสำหรับคุณสมบัติอื่นของอ็อบเจ็กต์เดียวกัน ในกรณีของฉันฉันกำลังโหลดข้อมูลเมตารวมถึงช่วงค่าที่ถูกต้องจากฐานข้อมูล และไม่รหัสผู้ขายไม่รองรับการส่งคอลเลกชันประเภทใด ๆ ไปยังคุณสมบัติ ขอบคุณ

10

เพียงแค่แสดง คำตอบของ 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

1
@YordanGeorgiev - ทำไมคุณถึงประกาศflagFileExistsเมื่อไม่มีการใช้งานที่อื่นในแอปพลิเคชัน?
Michael Kniskern

2
ฉันเดาว่ามันเป็นจุดบกพร่องมากกว่า; I)
Yordan Georgiev

5

เรามาจากทิศทางที่ผิดไม่ใช่เหรอ?

หากข้อมูลมีแนวโน้มที่จะเปลี่ยนแปลงไปเลยในช่วงอายุการใช้งานของรีลีสที่ทำให้ใช้งานได้ enum ก็ไม่เหมาะสมและคุณจำเป็นต้องใช้พจนานุกรมแฮชหรือคอลเล็กชันแบบไดนามิกอื่น ๆ

หากคุณทราบว่าชุดของค่าที่เป็นไปได้ได้รับการแก้ไขสำหรับอายุการใช้งานของรีลีสที่ปรับใช้แล้ว enum จะดีกว่า

หากคุณต้องมีบางอย่างในฐานข้อมูลของคุณที่จำลองชุดที่แจกแจงแล้วทำไมไม่เพิ่มขั้นตอนการปรับใช้เพื่อล้างและเติมตารางฐานข้อมูลด้วยชุดค่า enum ที่ชัดเจน


ใช่และไม่ใช่ใช่เพราะคุณถูกต้องจุดรวมคือ enum คงที่ คุณสามารถหลีกเลี่ยงข้อผิดพลาดในการพิมพ์และรู้ว่ามีอะไรบ้าง ด้วยพจนานุกรมและฐานข้อมูลอาจเป็นอะไรก็ได้ แต่บางครั้งคุณต้องการผลของต้นไม้ทั้งสองเมื่อคุณได้รับอนุญาตให้เก็บจากต้นเดียว
Ken

4

ฉันชอบเขียน "custom enum" ของตัวเองเสมอ กว่าฉันจะมีคลาสเดียวที่ซับซ้อนกว่าเล็กน้อย แต่ฉันสามารถใช้ซ้ำได้:

public abstract class CustomEnum
{
    private readonly string _name;
    private readonly object _id;

    protected CustomEnum( string name, object id )
    {
        _name = name;
        _id = id;
    }

    public string Name
    {
        get { return _name; }
    }

    public object Id
    {
        get { return _id; }
    }

    public override string ToString()
    {
        return _name;
    }
}

public abstract class CustomEnum<TEnumType, TIdType> : CustomEnum
    where TEnumType : CustomEnum<TEnumType, TIdType>
{
    protected CustomEnum( string name, TIdType id )
        : base( name, id )
    { }

    public new TIdType Id
    {
        get { return (TIdType)base.Id; }
    }

    public static TEnumType FromName( string name )
    {
        try
        {
            return FromDelegate( entry => entry.Name.Equals( name ) );
        }
        catch (ArgumentException ae)
        {
            throw new ArgumentException( "Illegal name for custom enum '" + typeof( TEnumType ).Name + "'", ae );
        }
    }

    public static TEnumType FromId( TIdType id )
    {
        try
        {
            return FromDelegate( entry => entry.Id.Equals( id ) );
        }
        catch (ArgumentException ae)
        {
            throw new ArgumentException( "Illegal id for custom enum '" + typeof( TEnumType ).Name + "'", ae );
        }
    }

    public static IEnumerable<TEnumType> GetAll()
    {
        var elements = new Collection<TEnumType>();
        var infoArray = typeof( TEnumType ).GetFields( BindingFlags.Public | BindingFlags.Static );

        foreach (var info in infoArray)
        {
            var type = info.GetValue( null ) as TEnumType;
            elements.Add( type );
        }

        return elements;
    }

    protected static TEnumType FromDelegate( Predicate<TEnumType> predicate )
    {
        if(predicate == null)
            throw new ArgumentNullException( "predicate" );

        foreach (var entry in GetAll())
        {
            if (predicate( entry ))
                return entry;
        }

        throw new ArgumentException( "Element not found while using predicate" );
    }
}

ตอนนี้ฉันต้องสร้าง enum ของฉันที่ฉันต้องการใช้:

 public sealed class SampleEnum : CustomEnum<SampleEnum, int>
    {
        public static readonly SampleEnum Element1 = new SampleEnum( "Element1", 1, "foo" );
        public static readonly SampleEnum Element2 = new SampleEnum( "Element2", 2, "bar" );

        private SampleEnum( string name, int id, string additionalText )
            : base( name, id )
        {
            AdditionalText = additionalText;
        }

        public string AdditionalText { get; private set; }
    }

ในที่สุดฉันก็สามารถใช้มันได้อย่างที่ต้องการ:

 static void Main( string[] args )
        {
            foreach (var element in SampleEnum.GetAll())
            {
                Console.WriteLine( "{0}: {1}", element, element.AdditionalText );
                Console.WriteLine( "Is 'Element2': {0}", element == SampleEnum.Element2 );
                Console.WriteLine();
            }

            Console.ReadKey();
        }

และผลลัพธ์ของฉันจะเป็น:

Element1: foo
Is 'Element2': False

Element2: bar
Is 'Element2': True    

2

คุณต้องการ System.Web.Compilation.BuildProvider

ฉันยังสงสัยในภูมิปัญญาในการทำสิ่งนี้ แต่อาจมีกรณีการใช้งานที่ดีที่ฉันคิดไม่ถึง

สิ่งที่คุณกำลังมองหาคือBuild Providersเช่น System.Web.Compilation.BuildProvider

SubSonicใช้อย่างมีประสิทธิภาพมากคุณสามารถดาวน์โหลดซอร์สและดูว่าพวกเขาใช้มันอย่างไรคุณไม่จำเป็นต้องมีอะไรซับซ้อนเหมือนสิ่งที่พวกเขากำลังทำอยู่ครึ่งหนึ่ง

หวังว่านี่จะช่วยได้



0

ฉันไม่คิดว่าจะมีวิธีที่ดีในการทำสิ่งที่คุณต้องการ และถ้าคุณคิดอย่างนั้นฉันไม่คิดว่านี่คือสิ่งที่คุณต้องการจริงๆ

หากคุณมีไดนามิก enum ก็หมายความว่าคุณต้องป้อนค่าไดนามิกด้วยเมื่อคุณอ้างอิง บางทีด้วยความมหัศจรรย์มากมายคุณสามารถบรรลุIntelliSenseบางประเภทที่จะดูแลสิ่งนี้และสร้าง enum ให้คุณในไฟล์ DLL แต่ให้พิจารณาจำนวนงานที่ต้องใช้การเข้าถึงฐานข้อมูลเพื่อดึงข้อมูล IntelliSense ตลอดจนฝันร้ายของเวอร์ชันที่ควบคุมไฟล์ DLL ที่สร้างขึ้น

หากคุณไม่ต้องการเพิ่มค่า enum ด้วยตนเองจริงๆ (คุณจะต้องเพิ่มค่าเหล่านี้ในฐานข้อมูลอยู่ดี) ให้ใช้เครื่องมือสร้างรหัสแทนเช่นเทมเพลตT4 คลิกขวา + เรียกใช้และคุณได้รับ enum ที่กำหนดไว้ในโค้ดแบบคงที่และคุณจะได้รับประโยชน์ทั้งหมดจากการใช้ enums


0

การใช้ไดนามิก enums ไม่ดีไม่ว่าจะด้วยวิธีใดก็ตาม คุณจะต้องประสบปัญหาในการ "ทำซ้ำ" ข้อมูลเพื่อให้แน่ใจว่าโค้ดที่ชัดเจนและง่ายต่อการบำรุงรักษาง่ายในอนาคต

หากคุณเริ่มแนะนำไลบรารีที่สร้างขึ้นโดยอัตโนมัติคุณแน่นอนว่าจะทำให้เกิดความสับสนมากขึ้นกับนักพัฒนาในอนาคตที่ต้องอัปเกรดโค้ดของคุณมากกว่าเพียงแค่การเข้ารหัส enum ของคุณภายในออบเจ็กต์คลาสที่เหมาะสม

ตัวอย่างอื่น ๆ ให้เสียงที่ดีและน่าตื่นเต้น แต่ให้คิดถึงค่าใช้จ่ายในการบำรุงรักษาโค้ดเทียบกับสิ่งที่คุณได้รับจากมัน นอกจากนี้ค่าเหล่านี้จะเปลี่ยนแปลงบ่อยหรือไม่?


0

วิธีหนึ่งในการเก็บ Enums และสร้างรายการค่าแบบไดนามิกในเวลาเดียวกันคือการใช้ Enums ที่คุณมีอยู่ในพจนานุกรมที่สร้างขึ้นแบบไดนามิก

เนื่องจาก Enums ส่วนใหญ่ใช้ในบริบทที่กำหนดให้ใช้และ "ไดนามิก enums" จะได้รับการสนับสนุนโดยกระบวนการแบบไดนามิกคุณจึงสามารถแยกแยะ 2

ขั้นตอนแรกคือการสร้างตาราง / คอลเลกชันที่มี ID และการอ้างอิงสำหรับรายการแบบไดนามิก ในตารางคุณจะสร้างอัตโนมัติมากกว่าค่า Enum ที่ใหญ่ที่สุดของคุณ

ตอนนี้มาถึงส่วนสำหรับ Enums แบบไดนามิกของคุณฉันสมมติว่าคุณจะใช้ Enums เพื่อสร้างชุดเงื่อนไขที่ใช้ชุดของกฎบางส่วนถูกสร้างขึ้นแบบไดนามิก

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.

0

คลาส builder enum

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();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.