c# foreach (свойство в объекте)... есть ли простой способ сделать это?


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

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

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

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

но это не работает! :( Я понимаю это ошибка...

"оператор foreach не может работать с переменными типа' Application.Объект 'потому что' приложение.Объект 'не содержит общедоступного определения для 'GetEnumerator'"

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

7 63

7 ответов:

дайте этому попытку:

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

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

например, чтобы разрешить все публичные свойства:

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

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

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

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

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

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

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

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

property.Name
property.GetValue(obj, null)

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

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

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

используйте отражение, чтобы сделать это

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

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

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