c # foreach (свойство в объекте) ... Есть ли простой способ сделать это? - PullRequest
78 голосов
/ 27 марта 2012

У меня есть класс, содержащий несколько свойств (все являются строками, если это имеет значение).
У меня также есть список, который содержит много разных экземпляров класса.

Создавая некоторые модульные тесты для своих классов, я решил, что хочу пройтись по каждому объекту в списке, а затем просмотреть все свойства этого объекта ...

Я думал, что сделать это будет так же просто, как ...

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

Но это не сработало! :( Я получаю эту ошибку ...

"оператор foreach не может работать с переменными типа« Application.Object », поскольку« Application.Object »не содержит общедоступного определения для« GetEnumerator ».

Кто-нибудь знает способ сделать это без множества циклов if и циклов или не вдаваясь во что-то слишком сложное?

Ответы [ 7 ]

123 голосов
/ 27 марта 2012

Попробуйте:

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

Также обратите внимание, что Type.GetProperties() имеет перегрузку, которая принимает набор флагов привязки, так что вы можете отфильтровать свойства по различным критериям, например по уровню доступности, подробнее см. В MSDN: Метод Type.GetProperties (BindingFlags) И последнее, но не менее важное: не забудьте добавить ссылку на сборку "system.Reflection".

Например, чтобы разрешить все открытые свойства:

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

Пожалуйста, дайте мне знать, работает ли это как ожидалось.

27 голосов
/ 27 марта 2012

Вы можете просмотреть все неиндексированные свойства объекта следующим образом:

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 в качестве второго параметра.

Вам может потребоваться изменить фильтр для того, чтобы отсеять свойства только для записи и другие недоступные свойства.

19 голосов
/ 27 марта 2012

Вы почти там, вам просто нужно получить свойства от типа, а не ожидать, что свойства будут доступны в виде коллекции или пакета свойств:

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

Оттуда вы можете получить доступ вот так :

property.Name
property.GetValue(obj, null)

С помощью GetValue второй параметр позволит вам указать значения индекса, которые будут работать со свойствами, возвращающими коллекции - поскольку строка является коллекциейchars, вы также можете указать индекс для возврата символа, если это необходимо.

18 голосов
/ 27 марта 2012

Конечно, нет проблем:

foreach(object item in sequence)
{
    if (item == null) continue;
    foreach(PropertyInfo property in item.GetType().GetProperties())
    {
        // do something with the property
    }
}
3 голосов
/ 27 марта 2012

Используйте Reflection, чтобы сделать это

SomeClass A = SomeClass(...)
PropertyInfo[] properties = A.GetType().GetProperties();
0 голосов
/ 10 мая 2018

Я не смог заставить ни один из вышеперечисленных способов работать, но это сработало.Имя пользователя и пароль для 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;
    }
0 голосов
/ 24 января 2017

Небольшое предостережение, если «делать что-то» означает обновление значения фактического свойства, которое вы посещаете И если есть свойство типа структуры по пути от корневого объекта к посещенному свойству, то изменение, которое вы произвели насвойство не будет отражено в корневом объекте.

...