c # foreach (ऑब्जेक्ट में गुण) ... क्या ऐसा करने का एक सरल तरीका है?


92

मेरे पास एक वर्ग है जिसमें कई गुण हैं (सभी स्ट्रिंग्स हैं अगर इससे कोई फर्क पड़ता है)।
मेरे पास एक सूची भी है, जिसमें कक्षा के कई अलग-अलग उदाहरण हैं।

अपनी कक्षाओं के लिए कुछ इकाई परीक्षण बनाते समय मैंने तय किया कि मैं सूची में प्रत्येक वस्तु के माध्यम से लूप करना चाहता हूं और फिर उस वस्तु की प्रत्येक संपत्ति के माध्यम से लूप करना चाहता हूं ...

मैंने सोचा कि ऐसा करना उतना ही सरल होगा ...

foreach (Object obj in theList)
{
     foreach (Property theProperties in obj)
     {
         do some stufff!!;
     }
}

लेकिन यह काम नहीं किया! :( मुझे यह त्रुटि मिली ...

"foreach स्टेटमेंट 'Application.Object' के प्रकारों पर काम नहीं कर सकता क्योंकि 'Application.Object' में 'GetEnumerator' की सार्वजनिक परिभाषा नहीं है"

क्या किसी को इफ और लूप के टन के बिना ऐसा करने का एक तरीका पता है या बिना कुछ भी जटिल हो रहा है?


5
भविष्य में, कृपया एक प्रश्न में "यह काम नहीं करता है" मत कहो। इसके बजाय, आपको जो समस्या हो रही है उसे निर्दिष्ट करें (संकलक त्रुटि, आदि)। धन्यवाद!
रॉबर्ट हार्वे

2
अपडेट किया गया! रॉबर्ट के लिए धन्यवाद
Jammerz858

जवाबों:


143

इसे आजमाइए:

foreach (PropertyInfo propertyInfo in obj.GetType().GetProperties())
{
   // do stuff here
}

कृपया यह भी ध्यान दें कि Type.GetProperties()एक अधिभार है जो बाध्यकारी झंडों के एक सेट को स्वीकार करता है ताकि आप एक्सेसिबिलिटी स्तर जैसे विभिन्न मानदंडों पर गुणों को फ़िल्टर कर सकें, अधिक विवरण के लिए MSDN देखें: Type.GetProperties विधि (बाइंडिंगफ्लैग्स) अंतिम लेकिन कम से कम मत भूलना "system.Reflection" असेंबली संदर्भ जोड़ें।

उदाहरण के लिए सभी सार्वजनिक संपत्तियों को हल करने के लिए:

foreach (var propertyInfo in obj.GetType()
                                .GetProperties(
                                        BindingFlags.Public 
                                        | BindingFlags.Instance))
{
   // do stuff here
}

कृपया मुझे बताएं कि क्या यह उम्मीद के मुताबिक काम करता है।


4
एक बार जब आप वस्तुओं के गुणों पर नियंत्रण रखते हैं, तो क्या प्रत्येक संपत्ति के मूल्य को हथियाने की कोई संभावना नहीं है? उदाहरण के लिए एक नाम या पोस्टकोड
JsonStatham 10

36

आप इस तरह से किसी ऑब्जेक्ट के सभी गैर-अनुक्रमित गुणों के माध्यम से लूप कर सकते हैं:

var s = new MyObject();
foreach (var p in s.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) {
    Console.WriteLine(p.GetValue(s, null));
}

चूंकि GetProperties()रिटर्न इंडेक्सर्स के साथ-साथ सरल गुण भी हैं, इसलिए आपको GetValueयह जानने के लिए कॉल करने से पहले एक अतिरिक्त फिल्टर की आवश्यकता है कि यह nullदूसरे पैरामीटर के रूप में पास करना सुरक्षित है ।

आपको केवल और केवल दुर्गम गुणों को लिखने के लिए फ़िल्टर को संशोधित करने की आवश्यकता हो सकती है।


+1 केवल उन गुणों के साथ कुछ करने के लिए जिन्हें वास्तव में उपयोग किया जा सकता है - आप शायद केवल-लेखन गुणों को फ़िल्टर करना चाहते हैं।

@hvd यह केवल लिखने के गुणों पर एक उत्कृष्ट बिंदु है! मैं लगभग उनके बारे में भूल गया हूं। मेरा कोड क्रैश हो जाएगा अगर यह एक संपत्ति को nullगेट्टर के साथ मिलाता है, लेकिन मुझे यकीन है कि ओपी यह पता लगाएगा कि उसे केवल उसी गुण को कैसे प्राप्त करना है जो उसे चाहिए।
सेर्गेई कालिनिचेंको

27

Your'e लगभग वहाँ है, आपको केवल गुणों को टाइप से प्राप्त करने की आवश्यकता है, बजाय संग्रह या प्रॉपर्टी बैग के रूप में गुणों के सुलभ होने की अपेक्षा:

var property in obj.GetType().GetProperties()

वहां से आप जैसे चाहें पहुंच सकते हैं :

property.Name
property.GetValue(obj, null)

GetValueदूसरे पैरामीटर के साथ आप सूचकांक मूल्यों को निर्दिष्ट करने की अनुमति देंगे, जो संग्रह को वापस करने वाले गुणों के साथ काम करेंगे - चूंकि एक स्ट्रिंग वर्णों का एक संग्रह है, इसलिए आप यदि आवश्यक हो तो एक चरित्र को वापस करने के लिए एक सूचकांक निर्दिष्ट कर सकते हैं।


1
क्या मैंने किसी को परेशान किया? मैं यह जानने के लिए खुला हूं कि इस बारे में क्या गलत है, अन्यथा मैं कभी नहीं सीख सकता।
ग्रांट थॉमस

जब आपका कोड गलत था (आपके निनजा संपादन से पहले) आपको संभवतः डाउनवोट मिला था।
रॉबर्ट हार्वे

20

बिलकुल कोई परेशानी नही:

foreach(object item in sequence)
{
    if (item == null) continue;
    foreach(PropertyInfo property in item.GetType().GetProperties())
    {
        // do something with the property
    }
}

आपने यह पंक्ति क्यों जोड़ी? if (item == null) continue;व्यक्तिगत रूप से, मुझे लगता है कि अगर आपको उस समय एक अशक्त वस्तु मिल गई है, तो कुछ बहुत पहले गलत हो गया है और यह वह जगह है जहां सत्यापन होना चाहिए, या मैं गलत हूं?
राफेल हर्स्कोविसी

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

3

ऐसा करने के लिए परावर्तन का उपयोग करें

SomeClass A = SomeClass(...)
PropertyInfo[] properties = A.GetType().GetProperties();

2

मैंने इस पृष्ठ पर एक समान प्रश्न के उत्तर की तलाश की, मैंने कई ऐसे ही प्रश्नों के उत्तर लिखे, जो इस पृष्ठ पर आने वाले लोगों की सहायता कर सकते हैं।

कक्षा सूची

सूची <टी> वर्ग उन वस्तुओं की सूची का प्रतिनिधित्व करता है जिन्हें सूचकांक द्वारा एक्सेस किया जा सकता है। यह System.Collection.Generic नाम स्थान के अंतर्गत आता है। सूची वर्ग का उपयोग विभिन्न प्रकारों जैसे पूर्णांक, स्ट्रिंग्स इत्यादि के संग्रह को बनाने के लिए किया जा सकता है। सूची वर्ग खोज सूचियों को खोजने, छांटने और हेरफेर करने के तरीके भी प्रदान करता है।

संपत्ति के साथ वर्ग :

class TestClss
{
    public string id { set; get; }
    public string cell1 { set; get; }
    public string cell2 { set; get; }
}
var MyArray = new List<TestClss> {
    new TestClss() { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new TestClss() { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new TestClss() { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (PropertyInfo property in Item.GetType().GetProperties())
    {
        var Key = property.Name;
        var Value = property.GetValue(Item, null);
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

या, क्षेत्र के साथ कक्षा :

class TestClss
{
    public string id = "";
    public string cell1 = "";
    public string cell2 = "";
}
var MyArray = new List<TestClss> {
    new TestClss() { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new TestClss() { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new TestClss() { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (var fieldInfo in Item.GetType().GetFields())
    {
        var Key = fieldInfo.Name;
        var Value = fieldInfo.GetValue(Item);
    }

}

या, वस्तुओं की सूची (समान कोशिकाओं के बिना):

var MyArray = new List<object> {
    new { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data", anotherCell = "" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (var props in Item.GetType().GetProperties())
    {
        var Key = props.Name;
        var Value = props.GetMethod.Invoke(Item, null).ToString();
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

या, वस्तुओं की सूची (इसमें समान कोशिकाएँ होनी चाहिए):

var MyArray = new[] {
    new { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    new { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    new { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
foreach (object Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (var props in Item.GetType().GetProperties())
    {
        var Key = props.Name;
        var Value = props.GetMethod.Invoke(Item, null).ToString();
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

या, वस्तुओं की सूची (कुंजी के साथ):

var MyArray = new {
    row1 = new { id = "1", cell1 = "cell 1 row 1 Data", cell2 = "cell 2 row 1 Data" },
    row2 = new { id = "2", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 2 Data" },
    row3 = new { id = "3", cell1 = "cell 1 row 2 Data", cell2 = "cell 2 row 3 Data" }
};
// using System.ComponentModel;  for TypeDescriptor
foreach (PropertyDescriptor Item in TypeDescriptor.GetProperties(MyArray))
{
    string Rowkey = Item.Name;
    object RowValue = Item.GetValue(MyArray);
    Console.WriteLine("Row key is: {0}", Rowkey);
    foreach (var props in RowValue.GetType().GetProperties())
    {
        var Key = props.Name;
        var Value = props.GetMethod.Invoke(RowValue, null).ToString();
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

या, शब्दकोश की सूची

var MyArray = new List<Dictionary<string, string>>() {
    new Dictionary<string, string>() { { "id", "1" }, { "cell1", "cell 1 row 1 Data" }, { "cell2", "cell 2 row 1 Data" } },
    new Dictionary<string, string>() { { "id", "2" }, { "cell1", "cell 1 row 2 Data" }, { "cell2", "cell 2 row 2 Data" } },
    new Dictionary<string, string>() { { "id", "3" }, { "cell1", "cell 1 row 3 Data" }, { "cell2", "cell 2 row 3 Data" } }
};
foreach (Dictionary<string, string> Item in MyArray)
{
    Console.WriteLine("Row Start");
    foreach (KeyValuePair<string, string> props in Item)
    {
        var Key = props.Key;
        var Value = props.Value;
        Console.WriteLine("{0}={1}", Key, Value);
    }
}

सौभाग्य..


0

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


0

एक कॉपी-पेस्ट समाधान (विस्तार के तरीके) ज्यादातर इस सवाल के पहले की प्रतिक्रियाओं पर आधारित है।

इसके अलावा अच्छी तरह से संभालती है IDicitonary (ExpandoObject / डायनामिक) जो अक्सर इस प्रतिबिंबित सामान के साथ काम करते समय आवश्यक होती है।

तंग छोरों और अन्य गर्म रास्तों में उपयोग के लिए अनुशंसित नहीं है। उन मामलों में आपको कुछ कैशिंग / IL उत्सर्जन / अभिव्यक्ति ट्री संकलन की आवश्यकता होगी।

    public static IEnumerable<(string Name, object Value)> GetProperties(this object src)
    {
        if (src is IDictionary<string, object> dictionary)
        {
            return dictionary.Select(x => (x.Key, x.Value));
        }
        return src.GetObjectProperties().Select(x => (x.Name, x.GetValue(src)));
    }

    public static IEnumerable<PropertyInfo> GetObjectProperties(this object src)
    {
        return src.GetType()
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(p => !p.GetGetMethod().GetParameters().Any());
    }

-1

मुझे काम करने के लिए उपरोक्त में से कोई भी तरीका नहीं मिला, लेकिन यह काम कर गया। DirectoryEntry के लिए उपयोगकर्ता नाम और पासवर्ड वैकल्पिक हैं।

   private List<string> getAnyDirectoryEntryPropertyValue(string userPrincipalName, string propertyToSearchFor)
    {
        List<string> returnValue = new List<string>();
        try
        {
            int index = userPrincipalName.IndexOf("@");
            string originatingServer = userPrincipalName.Remove(0, index + 1);
            string path = "LDAP://" + originatingServer; //+ @"/" + distinguishedName;
            DirectoryEntry objRootDSE = new DirectoryEntry(path, PSUsername, PSPassword);
            var objSearcher = new System.DirectoryServices.DirectorySearcher(objRootDSE);
            objSearcher.Filter = string.Format("(&(UserPrincipalName={0}))", userPrincipalName);
            SearchResultCollection properties = objSearcher.FindAll();

            ResultPropertyValueCollection resPropertyCollection = properties[0].Properties[propertyToSearchFor];
            foreach (string resProperty in resPropertyCollection)
            {
                returnValue.Add(resProperty);
            }
        }
        catch (Exception ex)
        {
            returnValue.Add(ex.Message);
            throw;
        }

        return returnValue;
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.