У меня есть класс, содержащий несколько свойств (все строки, если это имеет значение).
У меня также есть список, который содержит много разных экземпляров класса.
Создавая несколько модульных тестов для своих классов, я решил, что хочу перебрать каждый объект в списке, а затем перебрать каждое свойство этого объекта ...
Я думал сделать это так же просто, как ...
foreach (Object obj in theList)
{
foreach (Property theProperties in obj)
{
do some stufff!!;
}
}
Но это не сработало! :( У меня такая ошибка ...
«Оператор foreach не может работать с переменными типа Application.Object, потому что Application.Object не содержит общедоступного определения для GetEnumerator»
Кто-нибудь знает, как это сделать без тонны if и циклов или не вдаваясь во что-то слишком сложное?
c#
properties
foreach
generic-list
Jammerz858
источник
источник
Ответы:
Попробуйте:
foreach (PropertyInfo propertyInfo in obj.GetType().GetProperties()) { // do stuff here }
Также обратите внимание, что у
Type.GetProperties()
него есть перегрузка, которая принимает набор флагов привязки, поэтому вы можете отфильтровать свойства по другим критериям, таким как уровень доступности, см. MSDN для получения дополнительных сведений: Type.GetProperties Method (BindingFlags) И последнее, но не менее важное, не забудьте добавьте ссылку на сборку "system.Reflection".Например, чтобы разрешить все общедоступные свойства:
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
в качестве второго параметра.Возможно, вам придется дополнительно изменить фильтр, чтобы исключить свойства, доступные только для записи или недоступные по другим причинам.
источник
null
получателем, но я уверен, что OP выяснит, как получить только те свойства, которые ему нужны.Вы почти готовы, вам просто нужно получить свойства из типа, а не ожидать, что свойства будут доступны в форме коллекции или пакета свойств:
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 } }
источник
if (item == null) continue;
Лично я думаю, что если в этот момент у вас есть нулевой объект, что-то пошло не так намного раньше, и именно здесь должна быть проверка, или я ошибаюсь?Используйте для этого Reflection
источник
Я искал ответ на аналогичный вопрос на этой странице, я написал ответы на несколько похожих вопросов, которые могут помочь людям, заходящим на эту страницу.
Список классов
Класс List <T> представляет список объектов, к которым можно получить доступ по индексу. Он входит в пространство имен System.Collection.Generic. Класс List может использоваться для создания коллекции различных типов, таких как целые числа, строки и т. Д. Класс List также предоставляет методы для поиска, сортировки и управления списками.
Класс с имуществом :
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); } }
Удачи..
источник
Небольшое предостережение, если «сделать что-нибудь» означает обновление значения фактического свойства, которое вы посещаете, И если есть свойство типа структуры на пути от корневого объекта к посещенному свойству, изменение, которое вы сделали в свойстве, будет не отражаться на корневом объекте.
источник
Решение для копирования и вставки (методы расширения) в основном основано на более ранних ответах на этот вопрос.
Также правильно обрабатывает 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()); }
источник
Я не мог заставить работать ни один из вышеперечисленных способов, но это сработало. Имя пользователя и пароль для 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; }
источник