2009-07-20 12 views
22

के साथ GetFields मैं किसी निश्चित वस्तु के अंदर सभी फ़ील्ड प्राप्त करने के लिए प्रतिबिंब कक्षाओं का उपयोग कर रहा हूं। मेरे समस्या फिर भी यह है कि यह पूरी तरह से काम करता है जब खेतों एक सामान्य वर्ग के अंदर कर रहे हैं की तरह है, यह है:GetType() से फ़ील्ड नहीं मिल रहा है। BindingFlag.Default

class test 
{ 
    string test1 = string.Empty; 
    string test2 = string.Empty; 
} 

यहाँ मैं दोनों test1 test2 और मिलता है, मेरी समस्या यह है कि मैं अमूर्त का उपयोग करें और इस प्रकार कई वर्गों संयुक्त है।

मैं की तरह कुछ मिल गया:

class test3 : test2 
{ 
    string test4 = string.Empty; 
    string test5 = string.Empty; 
} 

class test2 : test1 
{ 
    string test2 = string.Empty; 
    string test3 = string.Empty; 
} 
class test1 
{ 
    string test0 = string.Empty; 
    string test1 = string.Empty; 
} 

लेकिन जब मैंने उसे चलाने के लिए, मैं क्षेत्रों GetType().GetFields(BindingFlag.Default) से वापस नहीं मिलता है।

उन सभी क्षेत्रों में भी संपत्ति है, get; set; इससे जुड़ा हुआ है। जब मैं कोड चलाता हूं, तो मुझे गुण 1 पर वापस लौटाता है लेकिन वास्तविक फ़ील्ड नहीं।

FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Default); 
foreach (FieldInfo field in fields) 

मैं भी कोशिश की है:

FieldInfo[] fields = Obj.GetType().GetFields(BindingFlags.Public 
              | BindingFlags.Instance 
              | BindingFlags.NonPublic 
              | BindingFlags.Static); 

मैं संपत्तियों के लिए एक ही कोड का उपयोग करें:

इस कोड है कि मैं के साथ क्षेत्रों पाने के लिए कोशिश कर रहा हूँ है

PropertyInfo[] properties = Obj.GetType().GetProperties(BindingFlags.Public 
              | BindingFlags.Instance 
              | BindingFlags.NonPublic 
              | BindingFlags.Static); 

foreach (PropertyInfo property in properties) 

कोई विचार क्यों मुझे सारणी वर्गों से गुण मिलते हैं लेकिन फ़ील्ड नहीं?

उत्तर

44

संपादित करें:

typeof(T).BaseType.GetFields(...) 

संपादित फिर से: आधार प्रकार के निजी सदस्यों पाने के लिए आपको करना है जीत।

संपादित करें 3/22/13: के बजाय Concat प्रयुक्त। चूंकि हम BindingFlags.DeclaredOnly निर्दिष्ट कर रहे हैं और एक प्रकार का BaseType स्वयं के बराबर नहीं हो सकता है, Union की आवश्यकता नहीं है और यह अधिक महंगा है।

public static IEnumerable<FieldInfo> GetAllFields(Type t) 
{ 
    if (t == null) 
     return Enumerable.Empty<FieldInfo>(); 

    BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | 
         BindingFlags.Static | BindingFlags.Instance | 
         BindingFlags.DeclaredOnly; 
    return t.GetFields(flags).Concat(GetAllFields(t.BaseType)); 
} 
+0

वैसे भी कोई फर्क नहीं पड़ता है, क्योंकि फ़ील्ड स्थैतिक नहीं हैं। –

+0

मैंने कोशिश की: फ़ील्डइन्फो [] फ़ील्ड = Obj.GetType()। GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy); लेकिन यह अभी भी काम नहीं कर रहा है। – Patrick

+0

वैसे मैंने कोशिश की: फ़ील्डइन्फो [] फ़ील्ड = Obj.GetType()। GetFields (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy); लेकिन अभी भी कोई भाग्य नहीं है। – Patrick

2

गुण विरासत में हैं, फ़ील्ड नहीं हैं। संरक्षित क्षेत्र वंशज वर्गों के लिए दृश्यमान हैं, लेकिन उनके द्वारा विरासत में नहीं मिला है। दूसरे शब्दों में, वंश वर्ग में वास्तव में इसकी मूल श्रेणी के गुण होते हैं, लेकिन यह केवल फ़ील्ड देखने में सक्षम है।

+0

व्युत्पन्न प्रकार * डू * के बनाए गए ऑब्जेक्ट्स में बेस प्रकार के इंस्टेंस फ़ील्ड शामिल हैं। –

+0

तो फिर GetType() फ़ील्ड पाने के लिए कोई रास्ता नहीं है? – Patrick

4

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

class A 
{ 
    // note that this field is private 
    string PrivateString = string.Empty; 
    // protected field 
    protected string ProtectedString = string.Empty; 
} 

class B : A { } 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("B Fields:"); 
     B b = new B(); 
     b.GetType() 
      .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 
      .ToList() 
      .ForEach(f => Console.WriteLine(f.Name)); 

     Console.WriteLine("A Fields:"); 
     A a = new A(); 
     a.GetType() 
      .GetFields(BindingFlags.NonPublic | BindingFlags.Instance) 
      .ToList() 
      .ForEach(f => Console.WriteLine(f.Name)); 

    } 
} 

इस कार्यक्रम का उत्पादन निम्नलिखित है:

B Fields: 
ProtectedString 
A Fields: 
PrivateString 
ProtectedString 

तो, प्रकार A दो क्षेत्रों है; PrivateString और ProtectedString। टाइप B में एक है; ProtectedString, कि यह A से विरासत में मिलता है। यदि आप PrivateString टाइप B के माध्यम से "पहुंच" देना चाहते हैं, तो आपको इसके मूल प्रकार (b.GetType().BaseType) पर नेविगेट करना होगा।

नोट हालांकि, अगर BProtectedString नामक फ़ील्ड रखने की रिपोर्ट करता है, तो यह फ़ील्ड अभी भी B में घोषित नहीं है; इसे A में घोषित किया गया है। उपर्युक्त नमूना कार्यक्रम में GetFields कॉल में BindingFlags.DeclaredOnly जोड़कर इसकी जांच की जा सकती है; GetFieldsB के लिए कोई फ़ील्ड नहीं लौटाएगा, और दो A के लिए।

अपने कोड नमूने के अनुवादित है, इसका मतलब है कि प्रकार test3 क्षेत्रों test2 और test3 शामिल नहीं है, क्योंकि वे प्रकार test2 (फ़ील्ड का नाम और प्रकार के नाम की समानता के लिए निजी हैं उस वाक्य कुछ भ्रामक बनाने के लिए, मैं

public static class ReflectionExtensions 
{ 
    public static IList<FieldInfo> GetAllFields(this Type type, BindingFlags flags) 
    { 
     if(type == typeof(Object)) return new List<FieldInfo>(); 

     var list = type.BaseType.GetAllFields(flags); 
     // in order to avoid duplicates, force BindingFlags.DeclaredOnly 
     list.AddRange(type.GetFields(flags | BindingFlags.DeclaredOnly)); 
     return list; 
    } 
} 

(untested है: डर)

3

.a आप इस एक्सटेंशन के विधि का उपयोग कर सकते हैं रिकर्सिवली नीचे से ऊपर तक एक प्रकार का वंशानुगत पदानुक्रम पार करने के लिए विरोध करने, प्रभावी ढंग से प्रकार के सभी क्षेत्रों और अपने सभी पूर्वजों लौटने हूँ , वाईएमएमवी)

+1

आप 'झंडे को शामिल करना चाहिए | = BindingFlags.DeclaredOnly' कार्यान्वयन या आप में डुप्लिकेट मिलेगा। –

0

तुम सिर्फ दोनों गुण और क्षेत्रों के लिए नाम चाहते हैं, का उपयोग आधार वर्ग से निजी सदस्यों सहित सभी प्रकार क्षेत्रों के

private static IEnumerable<string > GetAllFieldsAndProperties(Type t) 
{ 
    if (t == null) 
    return Enumerable.Empty<string>(); 

    BindingFlags flags = BindingFlags.Public 
    | BindingFlags.NonPublic 
    | BindingFlags.Static 
    | BindingFlags.Instance 
    | BindingFlags.DeclaredOnly; 
    return t.GetFields(flags).Select(x=>x.Name) 
    .Union(GetAllFieldsAndProperties(t.BaseType)) 
    .Union(t.GetProperties(flags).Select(x=>x.Name)); 
} 
0

गणन।

public static IEnumerable<FieldInfo> EnumerateFields(this Type type, BindingFlags bindingFlags) => 
     type.BaseType?.EnumerateFields(bindingFlags) 
      .Concat(type.GetFields(bindingFlags | BindingFlags.DeclaredOnly)) ?? 
     type.EnumerateFields(bindingFlags); 
+0

कृपया उत्तर के रूप में केवल डंपिंग कोड से बचने का प्रयास करें और यह बताने की कोशिश करें कि यह क्या करता है और क्यों। आपका कोड उन लोगों के लिए स्पष्ट नहीं हो सकता है जिनके पास प्रासंगिक कोडिंग अनुभव नहीं है। कृपया अपना उत्तर संपादित करें [स्पष्टीकरण, संदर्भ और अपने उत्तर में किसी सीमा, धारणाओं या सरलीकरणों का उल्लेख करने का प्रयास करें।] (Https://stackoverflow.com/help/how-to-answer) –

+0

धन्यवाद, विवरण जोड़ा गया है। – Makeman

संबंधित मुद्दे