c# foreach (property in object)... 有没有一种简单的方法可以做到这一点?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9893028/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 11:06:26  来源:igfitidea点击:

c# foreach (property in object)... Is there a simple way of doing this?

c#propertiesforeachgeneric-list

提问by Jammerz858

I have a class containing several properties (all are strings if it makes any difference).
I also have a list, which contains many different instances of the class.

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

While creating some unit tests for my classes I decided I wanted to loop through each object in the list and then loop through each property of that object...

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

I thought doing this would be as simple as...

我以为这样做会很简单......

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

But this didnt work! :( 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'"

“foreach 语句不能对‘Application.Object’类型的变量进行操作,因为‘Application.Object’不包含‘GetEnumerator’的公共定义”

Does anyone know of a way of doing this without tons of ifs and loops or without getting into anything too complex?

有没有人知道没有大量的 ifs 和循环或者没有进入任何太复杂的东西的方法?

采纳答案by sll

Give this a try:

试试这个:

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

Also please note that Type.GetProperties()has an overload which accepts a set of binding flags so you can filter out properties on a different criteria like accessibility level, see MSDN for more details: Type.GetProperties Method (BindingFlags)Last but not least don't forget to add the "system.Reflection" assembly reference.

另请注意,它Type.GetProperties()有一个接受一组绑定标志的重载,因此您可以根据不同的标准(如可访问性级别)过滤掉属性,有关更多详细信息,请参阅 MSDN:Type.GetProperties Method (BindingFlags)最后但并非最不重要的是不要忘记添加“system.Reflection”程序集引用。

For instance to resolve all public properties:

例如解析所有公共属性:

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

Please let me know whether this works as expected.

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

回答by Arion

Use Reflection to do this

使用反射来做到这一点

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

回答by Grant Thomas

Your'e almost there, you just need to get the properties from the type, rather than expect the properties to be accessible in the form of a collection or property bag:

你快到了,你只需要从类型中获取属性,而不是期望可以以集合或属性包的形式访问这些属性:

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

From there you can access like so:

从那里你可以像这样访问

property.Name
property.GetValue(obj, null)

With GetValuethe 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.

使用GetValue第二个参数将允许您指定索引值,这将与返回集合的属性一起使用 - 由于字符串是字符的集合,如果需要,您还可以指定一个索引来返回一个字符。

回答by Eric Lippert

Sure, no problem:

好没问题:

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

回答by dasblinkenlight

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

Since GetProperties()returns indexersas well as simple properties, you need an additional filter before calling GetValueto know that it is safe to pass nullas the second parameter.

由于GetProperties()返回索引器以及简单的属性,因此在调用之前您需要一个额外的过滤器,GetValue以了解null作为第二个参数传递是安全的。

You may need to modify the filter further in order to weed out write-only and otherwise inaccessible properties.

您可能需要进一步修改过滤器以清除只写和其他无法访问的属性。

回答by Dogu Arslan

A small word of caution, if "do some stuff" means updating the value of the actual property that you visit AND if there is a struct type property along the path from root object to the visited property, the change you made on the property will not be reflected on the root object.

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

回答by Bbb

I couldn't get any of the above ways to work, but this worked. The username and password for DirectoryEntry are optional.

我无法获得上述任何一种工作方式,但这有效。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;
    }

回答by Zar Shardan

A copy-paste solution (extension methods) mostly based on earlier responses to this question.

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

Also properly handles IDicitonary (ExpandoObject/dynamic) which is often needed when dealing with this reflected stuff.

还可以正确处理 IDicitonary (ExpandoObject/dynamic),这在处理这种反射的东西时经常需要。

Not recommended for use in tight loops and other hot paths. In those cases you're gonna need some caching/IL emit/expression tree compilation.

不建议在紧密环路和其他热路径中使用。在这些情况下,您将需要一些缓存/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());
    }