Подтвердить что ты не робот

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

Попробуйте:

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
}

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

Ответ 2

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

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.

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

Ответ 3

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

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

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

property.Name
property.GetValue(obj, null)

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

Ответ 4

Конечно, никаких проблем:

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

Ответ 5

Используйте Reflection для этого

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

Ответ 6

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

Ответ 7

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

Ответ 8

Решение копирования-вставки (методы расширения) в основном основано на предыдущих ответах на этот вопрос.

Также правильно обрабатывает IDicitonary (ExpandoObject/dynamic), который часто необходим при работе с этим отраженным материалом.

Не рекомендуется для использования в узких петлях и других горячих дорожках. В этих случаях вам понадобится компиляция дерева кэширования /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());
    }