我有一个包含多个属性的类(如果有任何不同,则所有都是字符串) 我还有一个列表,其中包含该类的许多不同实例。
在为我的类创建一些单元测试时,我决定循环遍历列表中的每个对象,然后循环遍历该对象的每个属性......
我认为这样做就像......一样简单。
foreach (Object obj in theList)
{
foreach (Property theProperties in obj)
{
do some stufff!!;
}
}
但这没有用! :( 我收到这个错误......
“foreach语句不能对'Application.Object'类型的变量进行操作,因为'Application.Object'不包含'GetEnumerator'的公共定义”
有没有人知道这样做的方法没有大量的ifs和循环,或者没有进入任何过于复杂的事情?
答案 0 :(得分:119)
尝试一下:
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
}
请告诉我这是否符合预期。
答案 1 :(得分:25)
您可以循环遍历对象的所有非索引属性,如下所示:
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
作为传递是安全的第二个参数。
您可能需要进一步修改过滤器,以便清除只写和其他无法访问的属性。
答案 2 :(得分:19)
你几乎就在那里,你只需要从类型中获取属性,而不是期望以集合或属性包的形式访问属性:
var property in obj.GetType().GetProperties()
property.Name
property.GetValue(obj, null)
使用GetValue
,第二个参数将允许您指定索引值,这将使用返回集合的属性 - 因为字符串是字符集合,您还可以指定索引以在需要时返回字符
答案 3 :(得分:18)
当然,没问题:
foreach(object item in sequence)
{
if (item == null) continue;
foreach(PropertyInfo property in item.GetType().GetProperties())
{
// do something with the property
}
}
答案 4 :(得分:3)
使用Reflection执行此操作
SomeClass A = SomeClass(...)
PropertyInfo[] properties = A.GetType().GetProperties();
答案 5 :(得分:2)
我在本页上寻找了类似问题的答案,我写了一些类似问题的答案,可能会帮助进入此页面的人。
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);
}
}
OR,带有字段的类:
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);
}
}
OR,对象列表(没有相同的单元格):
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);
}
}
OR,对象列表(必须具有相同的单元格):
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);
}
}
OR,对象列表(带键):
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);
}
}
祝你好运。
答案 6 :(得分:0)
要小心谨慎,如果“做一些事情”意味着更新您访问的实际属性的值,并且如果在从根对象到被访问属性的路径中存在结构类型属性,则您所做的更改该属性不会反映在根对象上。
答案 7 :(得分:0)
我无法通过上述任何方式工作,但这很有效。 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 :(得分:0)
复制粘贴解决方案(扩展方法)主要基于对该问题的较早答复。
还可以正确处理在处理这些反映的内容时经常需要使用的同质(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());
}
答案 9 :(得分:0)
对我来说,解决方案是将 GetProperties() 更改为 GetRuntimeProperties()。
static void EnumObject(ShareCollection obj)
{
foreach (PropertyInfo property in obj.GetType().GetRuntimeProperties())
{
property.GetValue(obj);
}
}