डेटाबेस लुकअप टेबल में मानों के आधार पर स्वचालित रूप से एनम बनाएं?


116

मैं स्वचालित रूप से एक एनम कैसे बना सकता हूं और बाद में डेटाबेस मान तालिका (एंटरप्राइज़ लाइब्रेरी डेटा लेयर का उपयोग करके) में मानों के आधार पर C # में इसके मूल्यों का उपयोग करता हूं?

उदाहरण के लिए, यदि मैं डेटाबेस में एक नया लुकअप मान जोड़ता हूं, तो मुझे कोड में अतिरिक्त स्थिर एनुम मूल्य घोषणा को मैन्युअल रूप से जोड़ना नहीं चाहिए - मैं डेटाबेस में एनम को सिंक में रखना चाहूंगा।

क्या ऐसा कुछ है?


मैं एक कोड जनरेट किए गए स्थिर एनम को बनाना नहीं चाहता ( कोड प्रोजेक्ट लेख एनम कोड जनरेटर के अनुसार - डेटाबेस से स्वचालित रूप से एनम कोड उत्पन्न करना) तालिकाओं को देखें और इसे पूरी तरह से स्वचालित होना पसंद करेंगे।


क्या यह संभव होगा कि आप एक तरह से एन्यूमरेशन का उपयोग करने की कोशिश कर रहे हैं जहां एक बेहतर समाधान है?
डैन

मैं @ दन के साथ हूं, ऐसा करने का एक बेहतर तरीका होना चाहिए।
अप्रैल को N_A

@ mydogisbox बेहतर तरीका क्या है?
एरट ओत्ज़ाप

@eranotzer वास्तव में, इसके बारे में थोड़ा सोचने के बाद, एक प्री-बिल्ड स्टेप लिखना बहुत सरल होगा, जो DB पर सवाल उठाता है और इससे एक एनम उत्पन्न करता है
N_A

1
यह कहा जा रहा है, मुझे यकीन नहीं है कि वह "मैं एक कोड उत्पन्न करने के लिए स्थिर एनुम नहीं बनाना चाहता हूं" का अर्थ है, इसलिए शायद यह आवश्यकता के अनुरूप नहीं है।
N_A

जवाबों:


97

मैं यह सटीक काम कर रहा हूं, लेकिन आपको काम करने के लिए कुछ प्रकार की कोड पीढ़ी बनाने की आवश्यकता है।

मेरे समाधान में, मैंने एक प्रोजेक्ट "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 हटाए जाते हैं तो आप एक बिल्ड नहीं कर पाएंगे। (चिकन और अंडे की तरह की समस्या - समाधान में आपकी अन्य परियोजनाओं के लिए यह आवश्यक है। ठीक से निर्माण करने के लिए, और जब तक आप अपना समाधान नहीं बना लेते हैं।

मुझे इस msdn लेख से उपरोक्त कोड मिला ।

उम्मीद है की यह मदद करेगा!


7
उन लोगों के लिए जो पोस्ट-बिल्ड पर परिणामी निष्पादन योग्य को चलाना नहीं जानते हैं: 1) प्रोजेक्ट पर राइट क्लिक करें 2) गुणों पर क्लिक करें 3) बिल्ड इवेंट पर क्लिक करें 4) "पोस्ट-बिल्ड इवेंट कमांड लाइन" टेक्स्ट बॉक्स प्रकार पर $ (लक्ष्यपथ)
मिगुएल

क्या इस लिंक में बताए अनुसार, कस्टम विशेषता परिभाषा के साथ डायनामिक एनम करना संभव है ?
बालगुरुनाथन मारीमुथु

49

Enums संकलन समय पर निर्दिष्ट किया जाना चाहिए, आप गतिशील रूप से रन-टाइम के दौरान enums नहीं जोड़ सकते हैं - और आप क्यों करेंगे, कोड में उनका कोई उपयोग / संदर्भ नहीं होगा?

प्रोफेशनल C # 2008 से:

सी # में एनमों की वास्तविक शक्ति यह है कि पर्दे के पीछे उन्हें आधार वर्ग, सिस्टम.ई.वेरम से प्राप्त स्ट्रक्चर्स के रूप में त्वरित किया जाता है। इसका मतलब यह है कि कुछ उपयोगी कार्यों को करने के लिए उनके खिलाफ तरीकों को कॉल करना संभव है। ध्यान दें कि .NET फ्रेमवर्क जिस तरह से लागू किया गया है, उसके कारण कोई प्रदर्शन हानि नहीं है जो संरचनात्मक रूप से एन्नेम को व्यवहार में लाने से जुड़ा है। व्यवहार में, एक बार जब आपका कोड संकलित किया जाता है, तो enums आदिम प्रकारों के रूप में मौजूद रहेगा, जैसे int और float।

इसलिए, मुझे यकीन नहीं है कि आप एनम का उपयोग उस तरह से कर सकते हैं जैसा आप चाहते हैं।


1
बिलफ्रेडटॉम का तर्क क्या है, यह निश्चित नहीं है, लेकिन मेरा यह था कि मैं कुछ कोड के लिए मैनुअल स्ट्रिंग-लुकअप करने से बच सकता था, बजाय इसके कि वे मेरे कोड में बने। मैं कमजोर तारों के बजाय दृढ़ता से टाइप किए गए मूल्यों पर तर्क करने में सक्षम होना पसंद करता हूं। एक चेतावनी यह होगी कि, चूंकि अब हमारे पास एक कोड है जो एक गतिशील रूप से उत्पन्न एनम पर निर्भर करता है, अगर हम डेटाबेस से मूल्य हटाते हैं, तो अगली बार जब हम अपने कोड को संकलित करने का प्रयास करेंगे तो यह विफल हो जाएगा।
पंडिंकस

14
पोस्टर और 18 upvotes थोड़े उनकी बात याद आती है। ऐसा लगता है जैसे वह जनित एनमों को चाहता है , न कि रनिंग डायनामिक एनमोंस को।
मैट मिशेल 7

+1। एक एनम मूल रूप से पूर्णांक स्थिरांक को परिभाषित करने का एक और तरीका है (भले ही System.Enumकुछ अतिरिक्त कार्यक्षमता हो)। लिखने के बजाय const int Red=0, Green=1, Blue=3;आप लिखिए enum { Red, Green, Blue }। एक स्थिरांक परिभाषा के अनुसार है और गतिशील नहीं है।
ओलिवियर जैकॉट-डेसकोम्बर्स 16

2
@ ओलिवर यदि आप शब्दार्थ पर बहस करना चाहते हैं, तो हाँ, आप सही हैं। लेकिन मैं ग्रैपहिन की टिप्पणी से सहमत हूं - मेरा मानना ​​है कि ओपी उत्पन्न हुई दुश्मनी की तलाश कर रहा है । वह चाहता है कि डेटाबेस से एनम वैल्यूज़ आएँ और उन्हें हार्ड-कोड न करना पड़े।
पांडिंस्कस

1
या ... मैं कहता हूं कि मैं अपने web.config में किसी को अपने ईमेल टेम्प्लेटिंग कोड के लिए ईमेल टेम्पलेट के लिए टोकन प्रकारों को परिभाषित करने देता हूं। यह अच्छा होगा यदि मेरे मौजूदा enum को EmailTokens कहा जाता है जो उन स्ट्रिंग प्रकारों का प्रतिनिधित्व करता है जो मेरे web.config में परिभाषित उन प्रकारों के आधार पर दिए जाएंगे। इसलिए अगर कोई भी मेरे महत्वपूर्ण मूल्य जैसे "ईमेल, FName" के माध्यम से वेबकॉन्फ़िग में एक नया ईमेल टोकन जोड़ता है और मेरे पास पहले से ही एक एनुम है कि मैं इन टोकन जैसे कि EmailTemplate.E का उपयोग करने वाला हूं, तो यह अच्छा होगा यदि कोई भी बस कर सकता है web.config में उस कुंजी में एक नया स्ट्रिंग टोकन जोड़ें और मेरी एनम स्वचालित रूप से कॉन्स्ट में जोड़ देगी
सकारात्मकगुन

18

क्या यह एक वास्तविक एनम होना चाहिए? Dictionary<string,int>इसके बजाय का उपयोग कैसे करें ?

उदाहरण के लिए

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

11
मैं इसे इस तरह से करने की कोशिश नहीं करूंगा। आप अपने संकलित समय की जाँच ढीली करते हैं और टाइपिंग त्रुटियों के शिकार हो जाते हैं। एनम के सभी लाभ चले गए। आप स्ट्रिंग स्थिरांक का परिचय दे सकते हैं, लेकिन फिर आप वापस वहीं हैं जहां आपने शुरुआत की थी।
डैनियल ब्रुकनर

1
मैं सहमत हूँ। लेकिन याद रखें कि गलत तरीके से चलने वाले तार पकड़े जाएंगे। सभी एनुम सदस्यों को कवर करने के लिए बस एक परीक्षण मामला जोड़ें।
ऑटोडिडैक्ट

1
यदि आप शाब्दिकों के बजाय स्थिरांक का उपयोग करते हैं, तो गलत व्यवहार करना कोई समस्या नहीं है
Maslow

@ मास्लो का मानना ​​है कि आप का मतलब है एनम, स्ट्रिंग स्थिरांक नहीं।
मैट मिशेल

4
+1। डिक्शनरी या हैशसेट का उपयोग करना एक गतिशील एनम हो सकता है। पूरी तरह से गतिशील का मतलब है कि यह रनटाइम पर होता है और इसलिए रनिंग में त्रुटि की जाँच करनी होगी।
ओलिवियर जैकोट-डेसकोम्बर्स

13

मैंने T4 टेम्पलेट के साथ ऐसा किया है । अपनी परियोजना में एक .tt फ़ाइल को छोड़ना और T4 टेम्पलेट को पूर्व-निर्मित चरण के रूप में चलाने के लिए Visual Studio सेट करना काफी तुच्छ है।

T4 एक .cs फ़ाइल बनाता है, जिसका अर्थ है कि आप इसे डेटाबेस से क्वेरी कर सकते हैं और परिणाम से .cs फ़ाइल में एक एनम का निर्माण कर सकते हैं। पूर्व-निर्माण कार्य के रूप में वायर्ड, यह आपके बिल्ड पर हर बार फिर से एनुम बनाएगा, या आप इसके बजाय मैन्युअल रूप से टी 4 को चला सकते हैं।


12

मान लें कि आपके 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

Enum के लिए सोर्स कोड बनाएं और आपको कुछ इस तरह मिलेगा:

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].Parse(enumType, value);

जहाँ मान या तो पूर्णांक मान (0, 1, आदि) या enum पाठ / कुंजी (Apple, केले, आदि) हो सकता है।


4
किस तरह से यह वास्तव में मदद करेगा? कोई प्रकार की सुरक्षा नहीं है और न ही कोई घुसपैठ है। मूल रूप से यह एक निरंतर उपयोग करने का एक अधिक जटिल तरीका है क्योंकि उसे वैसे भी मूल्य प्रदान करना है।
रनबॉर्ग

2
सानी - एकदम सही! यह वही था जो मुझे चाहिए था। उन लोगों के लिए जो इस तरह से कुछ करने के कारण पर सवाल उठाते हैं, मैं एक विक्रेता पुस्तकालय का उपयोग कर रहा हूं जिसके लिए एक संपत्ति को एक गणना के नाम पर सेट करने की आवश्यकता है। गणना एक ही वस्तु की एक अलग संपत्ति के लिए मान्य मूल्य सीमा को प्रतिबंधित करती है। मेरे मामले में मैं मेटाडेटा लोड कर रहा हूं, जिसमें एक डेटाबेस से मान्य मूल्य सीमा शामिल है; और नहीं, विक्रेता कोड संपत्ति के किसी भी प्रकार के संग्रह को पारित करने का समर्थन नहीं करता है। धन्यवाद

10

"शेल्फ" कोड और कुछ स्पष्टीकरण के साथ पांडिंस्क का उत्तर दिखाते हुए : आपको इस उदाहरण के लिए दो समाधान चाहिए (मुझे पता है कि यह एक के माध्यम से भी किया जा सकता है;), उन्नत छात्रों को इसे प्रस्तुत करने दें ...

तो यहाँ तालिका के लिए 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जब आप आवेदन में कहीं और इस्तेमाल नहीं करते हैं तो आप इसकी घोषणा क्यों करते हैं ?
माइकल नाइटस्कैन

2
मुझे लगता है कि यह एक बग की तुलना में है; I)
योर्डन जॉर्जिएव

5

क्या हम गलत दिशा से इस पर नहीं आ रहे हैं?

यदि डेटा को रिलीज़ किए गए रिलीज़ के जीवनकाल के दौरान बिल्कुल बदलने की संभावना है, तो एक एनम उचित नहीं है, और आपको एक शब्दकोश, हैश या अन्य गतिशील संग्रह का उपयोग करने की आवश्यकता है।

यदि आप जानते हैं कि तैनात रिलीज के जीवन के लिए संभावित मानों का सेट निर्धारित है, तो एक एनम बेहतर है।

आप तो चाहिए अपने डेटाबेस में कुछ ऐसा है जो enumerated सेट प्रतिकृति है, तो क्यों नहीं स्पष्ट और enum मूल्यों की निश्चित सेट के साथ डेटाबेस तालिका फिर से आबाद करने के लिए एक तैनाती कदम जोड़ सकता हूँ?


हां और नहीं, हां क्योंकि आप सही हैं कि पूरा बिंदु स्थिर है। आप टाइपिंग की त्रुटियों से बच सकते हैं और यह भी जान सकते हैं कि क्या उपलब्ध है। शब्दकोश और डीबी के साथ - कुछ भी हो सकता है। लेकिन कभी-कभी आप दोनों पेड़ों का फल चाहते हैं जब आपको केवल एक से चुनने की अनुमति होती है।
केन

4

मैं हमेशा अपना खुद का "कस्टम एनम" लिखना पसंद करता हूं। मेरे पास एक वर्ग है जो थोड़ा अधिक जटिल है, लेकिन मैं इसका पुन: उपयोग कर सकता हूं:

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

अब मुझे बस अपनी एनम बनाने की जरूरत है जिसका मैं उपयोग करना चाहता हूं:

 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 चाहते हैं

मुझे ऐसा करने की बुद्धिमत्ता पर भी संदेह है, लेकिन फिर शायद एक अच्छा उपयोग मामला है जिसके बारे में मैं सोच भी नहीं सकता।

क्या आप के लिए देख रहे हैं बिल्ड प्रदाता हैं अर्थात System.Web.Compilation.BuildProvider

वे SubSonic द्वारा बहुत प्रभावी ढंग से उपयोग किए जाते हैं , आप स्रोत को डाउनलोड कर सकते हैं और देख सकते हैं कि वे उनका उपयोग कैसे करते हैं, आपको कुछ भी आधे की आवश्यकता नहीं होगी जितना कि वे कर रहे हैं।

उम्मीद है की यह मदद करेगा।



0

मुझे नहीं लगता कि आप जो चाहते हैं, उसे करने का एक अच्छा तरीका है। और अगर आप इसके बारे में सोचते हैं तो मुझे नहीं लगता कि यह वही है जो आप वास्तव में चाहते हैं।

यदि आपके पास एक गतिशील एनम होगा, तो इसका मतलब यह भी है कि जब आप इसे संदर्भित करते हैं तो आपको इसे एक गतिशील मूल्य के साथ खिलाना होगा। हो सकता है कि बहुत सारे जादू के साथ आप किसी तरह का इंटेलीजेंस प्राप्त कर सकें जो इस बात का ध्यान रखेगा और आपके लिए एक DLL फ़ाइल में एक एनम उत्पन्न करेगा। लेकिन काम की मात्रा पर विचार करें, इंटेलीजेंसी जानकारी प्राप्त करने के लिए डेटाबेस को एक्सेस करने के लिए कितना अप्रभावी होगा और साथ ही उत्पन्न DLL फ़ाइल को नियंत्रित करने वाले संस्करण के बुरे सपने।

यदि आप वास्तव में Enum मानों को मैन्युअल रूप से जोड़ना नहीं चाहते हैं (आपको उन्हें डेटाबेस में फिर भी जोड़ना होगा) इसके बजाय एक कोड जनरेशन टूल का उपयोग करें, उदाहरण के लिए T4 टेम्पलेट। राइट क्लिक + रन और आपने अपने एनम को कोड में वैधानिक रूप से परिभाषित किया और आपको एनम का उपयोग करने के सभी लाभ मिलते हैं।


0

डायनामिक एनम का उपयोग करना बुरा है, चाहे जो भी हो। आपको भविष्य में बनाए रखने के लिए स्पष्ट और आसान कोड सुनिश्चित करने के लिए डेटा "डुप्लिकेटिंग" की परेशानी से गुजरना होगा।

यदि आप स्वत: उत्पन्न पुस्तकालयों को शुरू करना शुरू करते हैं, तो आप भविष्य के डेवलपर्स के लिए अधिक भ्रम पैदा करने के लिए सुनिश्चित हैं कि आपके कोड को उन्नत करने की तुलना में उपयुक्त वर्ग वस्तु के भीतर कोडित किया जाए।

अन्य उदाहरणों ने ध्वनि को अच्छा और रोमांचक दिया, लेकिन कोड रखरखाव पर ओवरहेड के बारे में सोचें कि आपको इससे क्या मिलता है। इसके अलावा, क्या वे मूल्य हैं जो अक्सर बदलते रहते हैं?


0

Enums रखने और एक ही समय में मूल्यों की एक गतिशील सूची बनाने का एक तरीका Enums का उपयोग करना है जो आपके पास वर्तमान में एक गतिशील रूप से बनाए गए शब्दकोश के साथ है।

चूंकि अधिकांश एनम का उपयोग इस संदर्भ में किया जाता है कि वे उपयोग किए जाने के लिए परिभाषित हैं, और "डायनामिक एनम" को गतिशील प्रक्रियाओं द्वारा समर्थित किया जाएगा, आप 2 को अलग कर सकते हैं।

पहला कदम एक तालिका / संग्रह बनाना है जो डायनेमिक प्रविष्टियों के लिए आईडी और संदर्भ देता है। तालिका में आप अपने सबसे बड़े Enum मान की तुलना में बहुत बड़ा होगा।

अब आपके डायनामिक एनम का हिस्सा आता है, मैं यह मान रहा हूं कि आप एनम का उपयोग शर्तों का एक सेट बनाने के लिए करेंगे जो नियमों का एक सेट लागू करते हैं, कुछ गतिशील रूप से उत्पन्न होते हैं।

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

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();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.