मैं प्रतिबिंब के प्रकार के सभी स्थिरांक कैसे प्राप्त कर सकता हूं?


जवाबों:


264

हालांकि यह एक पुराना कोड है:

private FieldInfo[] GetConstants(System.Type type)
{
    ArrayList constants = new ArrayList();

    FieldInfo[] fieldInfos = type.GetFields(
        // Gets all public and static fields

        BindingFlags.Public | BindingFlags.Static | 
        // This tells it to get the fields from all base types as well

        BindingFlags.FlattenHierarchy);

    // Go through the list and only pick out the constants
    foreach(FieldInfo fi in fieldInfos)
        // IsLiteral determines if its value is written at 
        //   compile time and not changeable
        // IsInitOnly determines if the field can be set 
        //   in the body of the constructor
        // for C# a field which is readonly keyword would have both true 
        //   but a const field would have only IsLiteral equal to true
        if(fi.IsLiteral && !fi.IsInitOnly)
            constants.Add(fi);           

    // Return an array of FieldInfos
    return (FieldInfo[])constants.ToArray(typeof(FieldInfo));
}

स्रोत

आप इसे आसानी से जेनरिक और LINQ का उपयोग करके क्लीनर कोड में बदल सकते हैं:

private List<FieldInfo> GetConstants(Type type)
{
    FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
         BindingFlags.Static | BindingFlags.FlattenHierarchy);

    return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
}

या एक पंक्ति के साथ:

type.GetFields(BindingFlags.Public | BindingFlags.Static |
               BindingFlags.FlattenHierarchy)
    .Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();

13
मेरे +1 से पहले मैंने भी 2 वीं पंक्ति को पार कर लिया था .. मैंने देखा कि आप इसके साथ हर कदम से गुजर रहे हैं ... इरादा-द्वारा-डिज़ाइन उद्देश्य ...! यह वह जगह है अतः महत्वपूर्ण है जब एक यह से जानने के लिए की जरूरत है। मैं आपके अनुभव के साथ हर एक की कामना करता हूं जैसा आपने यहां किया है।
लोनएक्सकोडर

4
मैं इस्राइटल और इसइनटोनी के संबंध में मुखरता के बारे में निश्चित नहीं हूं। परीक्षण करने पर ऐसा प्रतीत होता है कि स्थिर पठनीय गुणों के लिए IsLiteral हमेशा गलत है - इसलिए IsLiteral एकमात्र ध्वज है जिसे आपको स्थिरांक खोजने के लिए जांचना होगा और आप IsInitOnly को अनदेखा कर सकते हैं। मैंने विभिन्न क्षेत्र प्रकारों (जैसे स्ट्रिंग, इंट 32) के साथ यह देखने की कोशिश की कि क्या इससे कोई फर्क पड़ा लेकिन ऐसा नहीं हुआ।
मार्क वत्स

49
साथ ही, FieldInfo से कास्ट का मान प्राप्त करने के लिए, GetRawConstantValue () का उपयोग करें।
सैम सिप्पे

@MarkWatts सही है। यह पोस्ट किए जाने के बाद से व्यवहार बदल सकता है। किसी भी मामले में दस्तावेज का IsLiteralकहना है if its value is written at compile timeऔर यह केवल स्थिरांक के लिए सच है, जो कि यह अभी कैसे व्यवहार कर रहा है (.NET 4.5.2 के रूप में परीक्षण किया गया है)
nawfal

52

यदि आप किसी विशिष्ट प्रकार के सभी स्थिरांक के मानों को लक्ष्य प्रकार से प्राप्त करना चाहते हैं , तो यहां एक विस्तार विधि है (इस पृष्ठ पर दिए गए कुछ उत्तरों का विस्तार):

public static class TypeUtilities
{
    public static List<T> GetAllPublicConstantValues<T>(this Type type)
    {
        return type
            .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)
            .Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(T))
            .Select(x => (T)x.GetRawConstantValue())
            .ToList();
    }
}

फिर इस तरह एक वर्ग के लिए

static class MyFruitKeys
{
    public const string Apple = "apple";
    public const string Plum = "plum";
    public const string Peach = "peach";
    public const int WillNotBeIncluded = -1;
}

आप stringइस तरह लगातार मान प्राप्त कर सकते हैं :

List<string> result = typeof(MyFruitKeys).GetAllPublicConstantValues<string>();
//result[0] == "apple"
//result[1] == "plum"
//result[2] == "peach"

ऐसा क्यों नहीं .Where(fi => fi.IsLiteral && !fi.IsInitOnly).Select(x => x.GetRawConstantValue()).OfType<T>().ToList();:?
T-moty

17

एक्सटेंशन के प्रकार:

public static class TypeExtensions
{
    public static IEnumerable<FieldInfo> GetConstants(this Type type)
    {
        var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);

        return fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly);
    }

    public static IEnumerable<T> GetConstantsValues<T>(this Type type) where T : class
    {
        var fieldInfos = GetConstants(type);

        return fieldInfos.Select(fi => fi.GetRawConstantValue() as T);
    }
}

1
जाहिर है यह है कि अगर एक प्रकार पर आपके स्थिरांक सभी तार हैं ;-)
बाइटेव डे

क्यों नहीं (ए) तरीकों को सामान्य बनाते हैं, (बी) तरीकों IEnumerable<T>को एक के बजाय वापस करते हैं IList?
वाई हा ली

@AiHaLee - संपन्न :-) हालांकि स्पष्ट रूप से यह अभी भी मानता है कि प्रश्न में वर्ग पर सभी प्रकार के कास्ट टी के प्रकार हैं
बट्टेव

2

property.GetConstantValue()मूल्य प्राप्त करने के लिए उपयोग करें ।


1
यह अच्छी तरह से मामला हो सकता है जब आपके पास संपत्ति होती है - लेकिन आपको पहली संपत्ति कैसे मिलती है?
वाई हा ली

4
InNet 4.5 में यह है:GetRawConstantValue()
क्रिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.