C # foreach (对象中的属性) ... 有这样做的简单方法吗?

我有一个包含几个属性的类(如果有区别的话,所有属性都是字符串)。
我还有一个列表,其中包含该类的许多不同实例。

在为我的类创建一些单元测试时,我决定循环遍历列表中的每个对象,然后循环遍历该对象的每个属性..。

我以为这么做很简单。

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

但是这没有用 I get this error...

"foreach statement cannot operate on variables of type 'Application.Object' because 'Application.Object' does not contain a public definition for 'GetEnumerator'"

有没有人知道一种不需要大量的如果和循环或者不需要进入任何太复杂的事情的方法?

231239 次浏览

试试这个:

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
}

请让我知道这是否如预期的工作。

使用反射进行此操作

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

几乎就是这样,您只需要从类型中获取属性,而不是期望属性以集合或属性包的形式可以访问:

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

From there 你可以这样访问:

property.Name
property.GetValue(obj, null)

With GetValue the second parameter will allow you to specify index values, which will work with properties returning collections - since a string is a collection of chars, you can also specify an index to return a character if needs be.

当然,没问题:

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

You can loop through all non-indexed properties of an object like this:

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作为第二个参数传递是安全的。

您可能需要进一步修改筛选器,以剔除只写属性和其他不可访问的属性。

一个小小的警告,如果“做一些事情”意味着更新您访问的实际属性的值,并且如果在从根对象到访问的属性的路径上有一个 struct 类型的属性,那么您对该属性所做的更改将不会反映在根对象上。

我不能得到以上任何一种方式的工作,但这个工作。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;
}

复制粘贴解决方案(扩展方法)主要基于对这个问题的早期回答。

还可以正确地处理在处理这些被反射的内容时经常需要的标记符号(扩展对象/动态)。

不推荐在紧密循环和其他热路径中使用。在这种情况下,需要编译一些缓存/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());
}

我在这个页面上寻找一个类似问题的答案,我写了几个类似问题的答案,可以帮助进入这个页面的人。

班级名单

List < T > class 表示可以通过索引访问的对象列表。这属于司法系统管辖范围。收集。泛型命名空间。列表类可用于创建不同类型(如整数、字符串等)的集合。列表类还提供搜索、排序和操作列表的方法。

具有属性 的类:

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);
}
}

OR, 字典一览表

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);
}
}

祝你好运。

对我来说,解决方案是将 GetProperties ()更改为 GetRuntimeProperties ()。

  static void EnumObject(ShareCollection obj)
{
foreach (PropertyInfo property in obj.GetType().GetRuntimeProperties())
{
property.GetValue(obj);
}
}