web-dev-qa-db-ja.com

c#foreach(オブジェクト内のプロパティ)...これを行う簡単な方法はありますか?

複数のプロパティを含むクラスがあります(違いがある場合はすべて文字列です)。
クラスの多くの異なるインスタンスを含むリストもあります。

クラスの単体テストを作成しているときに、リスト内の各オブジェクトをループし、そのオブジェクトの各プロパティをループすることを決めました...

これをするのは簡単だと思った...

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

しかし、これはうまくいきませんでした! :(このエラーが発生します...

「foreachステートメントは、「Application.Object」には「GetEnumerator」のパブリック定義が含まれていないため、「Application.Object」タイプの変数を操作できません。」

誰もが大量のifやループなしで、または複雑すぎることなくこれを行う方法を知っていますか?

78
Jammerz858

これを試してみてください:

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
}

これが期待どおりに機能するかどうかを教えてください。

123
sll

次のように、オブジェクトのすべてのインデックスなしプロパティをループできます。

var s = new MyObject();
foreach (var p in s.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) {
    Console.WriteLine(p.GetValue(s, null));
}

GetProperties()は単純なプロパティと同様にindexersを返すので、GetValueを呼び出す前に追加のフィルターが必要であり、2番目のパラメーターとしてnullを渡すのが安全であることを知ることができます。

書き込み専用およびアクセスできないプロパティを除外するために、フィルターをさらに変更する必要がある場合があります。

27
dasblinkenlight

プロパティがコレクションまたはプロパティバッグの形式でアクセス可能であることを期待するのではなく、タイプからプロパティを取得する必要があります。

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

そこから そのようにアクセスできます

property.Name
property.GetValue(obj, null)

GetValueを使用すると、2番目のパラメーターでインデックス値を指定できます。これは、コレクションを返すプロパティで機能します。文字列は文字のコレクションであるため、必要に応じて文字を返すインデックスを指定することもできます.

19
Grant Thomas

もちろん問題ありません:

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

これを行うにはReflectionを使用します

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

小さな注意点、「何かをする」とは、訪問する実際のプロパティの値を更新することを意味し、ルートオブジェクトから訪問先のプロパティへのパスに構造タイプのプロパティがある場合、プロパティに加えた変更はルートオブジェクトに反映されません。

0
Dogu Arslan

上記の方法を使用することはできませんでしたが、これは機能しました。 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;
    }
0
Bbb